]> git.lizzy.rs Git - rust.git/blob - src/librustc_save_analysis/span_utils.rs
Rollup merge of #68500 - Mark-Simulacrum:fix-bootstrap-clearing, r=alexcrichton
[rust.git] / src / librustc_save_analysis / span_utils.rs
1 use crate::generated_code;
2 use rustc::session::Session;
3 use rustc_parse::lexer::{self, StringReader};
4 use rustc_span::*;
5 use syntax::token::{self, TokenKind};
6
7 #[derive(Clone)]
8 pub struct SpanUtils<'a> {
9     pub sess: &'a Session,
10 }
11
12 impl<'a> SpanUtils<'a> {
13     pub fn new(sess: &'a Session) -> SpanUtils<'a> {
14         SpanUtils { sess }
15     }
16
17     pub fn make_filename_string(&self, file: &SourceFile) -> String {
18         match &file.name {
19             FileName::Real(path) if !file.name_was_remapped => {
20                 if path.is_absolute() {
21                     self.sess
22                         .source_map()
23                         .path_mapping()
24                         .map_prefix(path.clone())
25                         .0
26                         .display()
27                         .to_string()
28                 } else {
29                     self.sess.working_dir.0.join(&path).display().to_string()
30                 }
31             }
32             // If the file name is already remapped, we assume the user
33             // configured it the way they wanted to, so use that directly
34             filename => filename.to_string(),
35         }
36     }
37
38     pub fn snippet(&self, span: Span) -> String {
39         match self.sess.source_map().span_to_snippet(span) {
40             Ok(s) => s,
41             Err(_) => String::new(),
42         }
43     }
44
45     pub fn retokenise_span(&self, span: Span) -> StringReader<'a> {
46         lexer::StringReader::retokenize(&self.sess.parse_sess, span)
47     }
48
49     pub fn sub_span_of_token(&self, span: Span, tok: TokenKind) -> Option<Span> {
50         let mut toks = self.retokenise_span(span);
51         loop {
52             let next = toks.next_token();
53             if next == token::Eof {
54                 return None;
55             }
56             if next == tok {
57                 return Some(next.span);
58             }
59         }
60     }
61
62     // // Return the name for a macro definition (identifier after first `!`)
63     // pub fn span_for_macro_def_name(&self, span: Span) -> Option<Span> {
64     //     let mut toks = self.retokenise_span(span);
65     //     loop {
66     //         let ts = toks.real_token();
67     //         if ts == token::Eof {
68     //             return None;
69     //         }
70     //         if ts == token::Not {
71     //             let ts = toks.real_token();
72     //             if ts.kind.is_ident() {
73     //                 return Some(ts.sp);
74     //             } else {
75     //                 return None;
76     //             }
77     //         }
78     //     }
79     // }
80
81     // // Return the name for a macro use (identifier before first `!`).
82     // pub fn span_for_macro_use_name(&self, span:Span) -> Option<Span> {
83     //     let mut toks = self.retokenise_span(span);
84     //     let mut prev = toks.real_token();
85     //     loop {
86     //         if prev == token::Eof {
87     //             return None;
88     //         }
89     //         let ts = toks.real_token();
90     //         if ts == token::Not {
91     //             if prev.kind.is_ident() {
92     //                 return Some(prev.sp);
93     //             } else {
94     //                 return None;
95     //             }
96     //         }
97     //         prev = ts;
98     //     }
99     // }
100
101     /// Return true if the span is generated code, and
102     /// it is not a subspan of the root callsite.
103     ///
104     /// Used to filter out spans of minimal value,
105     /// such as references to macro internal variables.
106     pub fn filter_generated(&self, span: Span) -> bool {
107         if generated_code(span) {
108             return true;
109         }
110
111         //If the span comes from a fake source_file, filter it.
112         !self.sess.source_map().lookup_char_pos(span.lo()).file.is_real_file()
113     }
114 }
115
116 macro_rules! filter {
117     ($util: expr, $parent: expr) => {
118         if $util.filter_generated($parent) {
119             return None;
120         }
121     };
122 }