-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Implement lazy loading of external crates' sources. #42593
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
70fa1fb
3d2cff0
dd8f7cd
c2c31b2
c04aa4e
a5b8851
9a8bbe9
634cd2c
afe8415
271133b
d11973a
bd4fe45
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ use RenderSpan::*; | |
use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style}; | ||
use styled_buffer::StyledBuffer; | ||
|
||
use std::borrow::Cow; | ||
use std::io::prelude::*; | ||
use std::io; | ||
use std::rc::Rc; | ||
|
@@ -131,7 +132,7 @@ impl EmitterWriter { | |
} | ||
} | ||
|
||
fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec<FileWithAnnotatedLines> { | ||
fn preprocess_annotations(&mut self, msp: &MultiSpan) -> Vec<FileWithAnnotatedLines> { | ||
fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>, | ||
file: Rc<FileMap>, | ||
line_index: usize, | ||
|
@@ -175,6 +176,9 @@ impl EmitterWriter { | |
if span_label.span == DUMMY_SP { | ||
continue; | ||
} | ||
|
||
cm.load_source_for_filemap(cm.span_to_filename(span_label.span)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should do this where the |
||
|
||
let lo = cm.lookup_char_pos(span_label.span.lo); | ||
let mut hi = cm.lookup_char_pos(span_label.span.hi); | ||
|
||
|
@@ -908,7 +912,8 @@ impl EmitterWriter { | |
// Print out the annotate source lines that correspond with the error | ||
for annotated_file in annotated_files { | ||
// we can't annotate anything if the source is unavailable. | ||
if annotated_file.file.src.is_none() { | ||
if annotated_file.file.src.is_none() | ||
&& annotated_file.file.external_src.borrow().is_absent() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be a single method on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can't do that, since said method would have to be defined in a place where the |
||
continue; | ||
} | ||
|
||
|
@@ -1009,7 +1014,7 @@ impl EmitterWriter { | |
} else if line_idx_delta == 2 { | ||
let unannotated_line = annotated_file.file | ||
.get_line(annotated_file.lines[line_idx].line_index) | ||
.unwrap_or(""); | ||
.unwrap_or_else(|| Cow::from("")); | ||
|
||
let last_buffer_line_num = buffer.num_lines(); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,7 @@ use self::Level::*; | |
|
||
use emitter::{Emitter, EmitterWriter}; | ||
|
||
use std::borrow::Cow; | ||
use std::cell::{RefCell, Cell}; | ||
use std::{error, fmt}; | ||
use std::rc::Rc; | ||
|
@@ -103,6 +104,7 @@ pub trait CodeMapper { | |
fn span_to_filename(&self, sp: Span) -> FileName; | ||
fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span>; | ||
fn call_span_if_macro(&self, sp: Span) -> Span; | ||
fn load_source_for_filemap(&self, file: FileName) -> bool; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find it a bit ridiculous that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe the long term solution would be to move |
||
} | ||
|
||
impl CodeSuggestion { | ||
|
@@ -121,7 +123,7 @@ impl CodeSuggestion { | |
use syntax_pos::{CharPos, Loc, Pos}; | ||
|
||
fn push_trailing(buf: &mut String, | ||
line_opt: Option<&str>, | ||
line_opt: Option<&Cow<str>>, | ||
lo: &Loc, | ||
hi_opt: Option<&Loc>) { | ||
let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize())); | ||
|
@@ -183,13 +185,13 @@ impl CodeSuggestion { | |
let cur_lo = cm.lookup_char_pos(sp.lo); | ||
for (buf, substitute) in bufs.iter_mut().zip(substitutes) { | ||
if prev_hi.line == cur_lo.line { | ||
push_trailing(buf, prev_line, &prev_hi, Some(&cur_lo)); | ||
push_trailing(buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo)); | ||
} else { | ||
push_trailing(buf, prev_line, &prev_hi, None); | ||
push_trailing(buf, prev_line.as_ref(), &prev_hi, None); | ||
// push lines between the previous and current span (if any) | ||
for idx in prev_hi.line..(cur_lo.line - 1) { | ||
if let Some(line) = fm.get_line(idx) { | ||
buf.push_str(line); | ||
buf.push_str(line.as_ref()); | ||
buf.push('\n'); | ||
} | ||
} | ||
|
@@ -205,7 +207,7 @@ impl CodeSuggestion { | |
for buf in &mut bufs { | ||
// if the replacement already ends with a newline, don't print the next line | ||
if !buf.ends_with('\n') { | ||
push_trailing(buf, prev_line, &prev_hi, None); | ||
push_trailing(buf, prev_line.as_ref(), &prev_hi, None); | ||
} | ||
// remove trailing newline | ||
buf.pop(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -158,29 +158,13 @@ impl CodeMap { | |
|
||
/// Creates a new filemap without setting its line information. If you don't | ||
/// intend to set the line information yourself, you should use new_filemap_and_lines. | ||
pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc<FileMap> { | ||
pub fn new_filemap(&self, filename: FileName, src: String) -> Rc<FileMap> { | ||
let start_pos = self.next_start_pos(); | ||
let mut files = self.files.borrow_mut(); | ||
|
||
// Remove utf-8 BOM if any. | ||
if src.starts_with("\u{feff}") { | ||
src.drain(..3); | ||
} | ||
|
||
let end_pos = start_pos + src.len(); | ||
|
||
let (filename, was_remapped) = self.path_mapping.map_prefix(filename); | ||
|
||
let filemap = Rc::new(FileMap { | ||
name: filename, | ||
name_was_remapped: was_remapped, | ||
crate_of_origin: 0, | ||
src: Some(Rc::new(src)), | ||
start_pos: Pos::from_usize(start_pos), | ||
end_pos: Pos::from_usize(end_pos), | ||
lines: RefCell::new(Vec::new()), | ||
multibyte_chars: RefCell::new(Vec::new()), | ||
}); | ||
let filemap = | ||
Rc::new(FileMap::new(filename, was_remapped, src, Pos::from_usize(start_pos))); | ||
|
||
files.push(filemap.clone()); | ||
|
||
|
@@ -210,6 +194,7 @@ impl CodeMap { | |
filename: FileName, | ||
name_was_remapped: bool, | ||
crate_of_origin: u32, | ||
src_hash: u128, | ||
source_len: usize, | ||
mut file_local_lines: Vec<BytePos>, | ||
mut file_local_multibyte_chars: Vec<MultiByteChar>) | ||
|
@@ -233,6 +218,8 @@ impl CodeMap { | |
name_was_remapped: name_was_remapped, | ||
crate_of_origin: crate_of_origin, | ||
src: None, | ||
src_hash: src_hash, | ||
external_src: RefCell::new(ExternalSource::AbsentOk), | ||
start_pos: start_pos, | ||
end_pos: end_pos, | ||
lines: RefCell::new(file_local_lines), | ||
|
@@ -572,6 +559,20 @@ impl CodeMapper for CodeMap { | |
} | ||
sp | ||
} | ||
fn load_source_for_filemap(&self, filename: FileName) -> bool { | ||
let file_map = if let Some(fm) = self.get_filemap(&filename) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this is a good idea - a caller would already have the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only caller I've inserted has a |
||
fm | ||
} else { | ||
return false; | ||
}; | ||
|
||
if *file_map.external_src.borrow() == ExternalSource::AbsentOk { | ||
let src = self.file_loader.read_file(Path::new(&filename)).ok(); | ||
return file_map.add_external_src(src); | ||
} | ||
|
||
false | ||
} | ||
} | ||
|
||
#[derive(Clone)] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be
size_of::<u128>()
.