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