]> git.lizzy.rs Git - rust.git/commitdiff
rustc_save_analysis: don't pollute the codemap with fake files.
authorEduard Burtescu <edy.burt@gmail.com>
Fri, 10 Jun 2016 10:00:21 +0000 (13:00 +0300)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Tue, 28 Feb 2017 06:30:07 +0000 (08:30 +0200)
src/librustc_save_analysis/span_utils.rs
src/libsyntax/parse/lexer/mod.rs

index 89525b27ed36af7d5f50d4e1b1b6c152a3fd7c2b..b5add6404fc9f0e37f953c77fba7583c7fa416d7 100644 (file)
@@ -17,7 +17,6 @@
 use std::path::Path;
 
 use syntax::ast;
-use syntax::parse::filemap_to_tts;
 use syntax::parse::lexer::{self, StringReader};
 use syntax::parse::token::{self, Token};
 use syntax::symbol::keywords;
@@ -49,23 +48,6 @@ pub fn make_path_string(file_name: &str) -> String {
         }
     }
 
-    // sub_span starts at span.lo, so we need to adjust the positions etc.
-    // If sub_span is None, we don't need to adjust.
-    pub fn make_sub_span(&self, span: Span, sub_span: Option<Span>) -> Option<Span> {
-        match sub_span {
-            None => None,
-            Some(sub) => {
-                let FileMapAndBytePos {fm, pos} = self.sess.codemap().lookup_byte_offset(span.lo);
-                let base = pos + fm.start_pos;
-                Some(Span {
-                    lo: base + self.sess.codemap().lookup_byte_offset(sub.lo).pos,
-                    hi: base + self.sess.codemap().lookup_byte_offset(sub.hi).pos,
-                    expn_id: span.expn_id,
-                })
-            }
-        }
-    }
-
     pub fn snippet(&self, span: Span) -> String {
         match self.sess.codemap().span_to_snippet(span) {
             Ok(s) => s,
@@ -74,24 +56,7 @@ pub fn snippet(&self, span: Span) -> String {
     }
 
     pub fn retokenise_span(&self, span: Span) -> StringReader<'a> {
-        // sadness - we don't have spans for sub-expressions nor access to the tokens
-        // so in order to get extents for the function name itself (which dxr expects)
-        // we need to re-tokenise the fn definition
-
-        // Note: this is a bit awful - it adds the contents of span to the end of
-        // the codemap as a new filemap. This is mostly OK, but means we should
-        // not iterate over the codemap. Also, any spans over the new filemap
-        // are incompatible with spans over other filemaps.
-        let filemap = self.sess
-                          .codemap()
-                          .new_filemap(String::from("<anon-dxr>"), None, self.snippet(span));
-        lexer::StringReader::new(&self.sess.parse_sess, filemap)
-    }
-
-    fn span_to_tts(&self, span: Span) -> Vec<TokenTree> {
-        let filename = String::from("<anon-dxr>");
-        let filemap = self.sess.codemap().new_filemap(filename, None, self.snippet(span));
-        filemap_to_tts(&self.sess.parse_sess, filemap)
+        lexer::StringReader::retokenize(&self.sess.parse_sess, span)
     }
 
     // Re-parses a path and returns the span for the last identifier in the path
@@ -103,7 +68,7 @@ pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
         loop {
             let ts = toks.real_token();
             if ts.tok == token::Eof {
-                return self.make_sub_span(span, result)
+                return result
             }
             if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
                 result = Some(ts.sp);
@@ -128,7 +93,7 @@ pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
                 return None;
             }
             if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
-                return self.make_sub_span(span, Some(ts.sp));
+                return Some(ts.sp);
             }
 
             bracket_count += match ts.tok {
@@ -178,10 +143,7 @@ pub fn sub_span_for_meth_name(&self, span: Span) -> Option<Span> {
             }
             prev = next;
         }
-        if result.is_none() && prev_span.is_some() {
-            return self.make_sub_span(span, prev_span);
-        }
-        return self.make_sub_span(span, result);
+        result.or(prev_span)
     }
 
     // Return the span for the last ident before a `<` and outside any
@@ -241,9 +203,9 @@ pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
                       loc.line);
         }
         if result.is_none() && prev.tok.is_ident() && angle_count == 0 {
-            return self.make_sub_span(span, Some(prev.sp));
+            return Some(prev.sp);
         }
-        self.make_sub_span(span, result)
+        result
     }
 
     // Reparse span and return an owned vector of sub spans of the first limit
@@ -310,7 +272,7 @@ pub fn spans_with_brackets(&self, span: Span, nesting: isize, limit: isize) -> V
                 angle_count += 1;
             }
             if ts.tok.is_ident() && angle_count == nesting {
-                result.push(self.make_sub_span(span, Some(ts.sp)).unwrap());
+                result.push(ts.sp);
             }
         }
     }
@@ -320,8 +282,11 @@ pub fn spans_with_brackets(&self, span: Span, nesting: isize, limit: isize) -> V
     /// end of the 'signature' part, that is up to, but not including an opening
     /// brace or semicolon.
     pub fn signature_string_for_span(&self, span: Span) -> String {
-        let mut toks = self.span_to_tts(span).into_iter();
+        let mut toks = self.retokenise_span(span);
+        toks.real_token();
+        let mut toks = toks.parse_all_token_trees().unwrap().into_iter();
         let mut prev = toks.next().unwrap();
+
         let first_span = prev.get_span();
         let mut angle_count = 0;
         for tok in toks {
@@ -360,7 +325,7 @@ pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
             }
             let next = toks.real_token();
             if next.tok == tok {
-                return self.make_sub_span(span, Some(prev.sp));
+                return Some(prev.sp);
             }
             prev = next;
         }
@@ -374,7 +339,7 @@ pub fn sub_span_of_token(&self, span: Span, tok: Token) -> Option<Span> {
                 return None;
             }
             if next.tok == tok {
-                return self.make_sub_span(span, Some(next.sp));
+                return Some(next.sp);
             }
         }
     }
@@ -399,7 +364,7 @@ fn sub_span_after<F: Fn(Token) -> bool>(&self, span: Span, f: F) -> Option<Span>
                 if ts.tok == token::Eof {
                     return None
                 } else {
-                    return self.make_sub_span(span, Some(ts.sp));
+                    return Some(ts.sp);
                 }
             }
         }
@@ -444,7 +409,7 @@ pub fn span_for_macro_def_name(&self, span: Span) -> Option<Span> {
             if ts.tok == token::Not {
                 let ts = toks.real_token();
                 if ts.tok.is_ident() {
-                    return self.make_sub_span(span, Some(ts.sp));
+                    return Some(ts.sp);
                 } else {
                     return None;
                 }
@@ -463,7 +428,7 @@ pub fn span_for_macro_use_name(&self, span:Span) -> Option<Span> {
             let ts = toks.real_token();
             if ts.tok == token::Not {
                 if prev.tok.is_ident() {
-                    return self.make_sub_span(span, Some(prev.sp));
+                    return Some(prev.sp);
                 } else {
                     return None;
                 }
index 6bc15115b09d3efca57ab6b55100e9c450132996..b7f6e6a2384f71d56435e3f3b0b12711dfd25c15 100644 (file)
@@ -51,10 +51,10 @@ pub struct StringReader<'a> {
     pub filemap: Rc<syntax_pos::FileMap>,
     /// If Some, stop reading the source at this position (inclusive).
     pub terminator: Option<BytePos>,
-    /// Whether to record new-lines in filemap. This is only necessary the first
-    /// time a filemap is lexed. If part of a filemap is being re-lexed, this
-    /// should be set to false.
-    pub save_new_lines: bool,
+    /// Whether to record new-lines and multibyte chars in filemap.
+    /// This is only necessary the first time a filemap is lexed.
+    /// If part of a filemap is being re-lexed, this should be set to false.
+    pub save_new_lines_and_multibyte: bool,
     // cached:
     pub peek_tok: token::Token,
     pub peek_span: Span,
@@ -162,7 +162,7 @@ fn new_raw_internal(sess: &'a ParseSess, filemap: Rc<syntax_pos::FileMap>) -> Se
             ch: Some('\n'),
             filemap: filemap,
             terminator: None,
-            save_new_lines: true,
+            save_new_lines_and_multibyte: true,
             // dummy values; not read
             peek_tok: token::Eof,
             peek_span: syntax_pos::DUMMY_SP,
@@ -183,6 +183,31 @@ pub fn new(sess: &'a ParseSess, filemap: Rc<syntax_pos::FileMap>) -> Self {
         sr
     }
 
+    pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self {
+        let begin = sess.codemap().lookup_byte_offset(span.lo);
+        let end = sess.codemap().lookup_byte_offset(span.hi);
+
+        // Make the range zero-length if the span is invalid.
+        if span.lo > span.hi || begin.fm.start_pos != end.fm.start_pos {
+            span.hi = span.lo;
+        }
+
+        let mut sr = StringReader::new_raw_internal(sess, begin.fm);
+
+        // Seek the lexer to the right byte range.
+        sr.save_new_lines_and_multibyte = false;
+        sr.next_pos = span.lo;
+        sr.terminator = Some(span.hi);
+
+        sr.bump();
+
+        if let Err(_) = sr.advance_token() {
+            sr.emit_fatal_errors();
+            panic!(FatalError);
+        }
+        sr
+    }
+
     pub fn ch_is(&self, c: char) -> bool {
         self.ch == Some(c)
     }
@@ -378,7 +403,10 @@ fn translate_crlf_(rdr: &StringReader,
     pub fn bump(&mut self) {
         let new_pos = self.next_pos;
         let new_byte_offset = self.byte_offset(new_pos).to_usize();
-        if new_byte_offset < self.source_text.len() {
+        let end = self.terminator.map_or(self.source_text.len(), |t| {
+            self.byte_offset(t).to_usize()
+        });
+        if new_byte_offset < end {
             let old_ch_is_newline = self.ch.unwrap() == '\n';
             let new_ch = char_at(&self.source_text, new_byte_offset);
             let new_ch_len = new_ch.len_utf8();
@@ -387,7 +415,7 @@ pub fn bump(&mut self) {
             self.pos = new_pos;
             self.next_pos = new_pos + Pos::from_usize(new_ch_len);
             if old_ch_is_newline {
-                if self.save_new_lines {
+                if self.save_new_lines_and_multibyte {
                     self.filemap.next_line(self.pos);
                 }
                 self.col = CharPos(0);
@@ -395,7 +423,9 @@ pub fn bump(&mut self) {
                 self.col = self.col + CharPos(1);
             }
             if new_ch_len > 1 {
-                self.filemap.record_multibyte_char(self.pos, new_ch_len);
+                if self.save_new_lines_and_multibyte {
+                    self.filemap.record_multibyte_char(self.pos, new_ch_len);
+                }
             }
         } else {
             self.ch = None;