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