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