]> git.proxmox.com Git - rustc.git/blob - src/librustc_save_analysis/span_utils.rs
New upstream version 1.47.0+dfsg1
[rustc.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 }