Put what is the FileDiagnostics into the SourceFile so the SourceFile has the content

This commit is contained in:
Olivier Goffart 2021-03-11 16:23:46 +01:00
parent 7c48bcdd4c
commit 968dfaae87
8 changed files with 70 additions and 70 deletions

View file

@ -328,8 +328,7 @@ pub fn sixtyfps(stream: TokenStream) -> TokenStream {
let source_file = if let Some(cargo_manifest) = std::env::var_os("CARGO_MANIFEST_DIR") {
let mut path: std::path::PathBuf = cargo_manifest.into();
path.push("Cargo.toml");
diag.current_path = std::rc::Rc::new(path);
Some(diag.current_path.clone())
Some(diagnostics::SourceFileInner::from_path(path))
} else {
None
};
@ -371,7 +370,7 @@ fn report_diagnostics(
let mut result = TokenStream::new();
let mut needs_error = diag.has_error();
for mut file_diag in diag.into_iter() {
if file_diag.source.is_none() {
if file_diag.current_path.path() == std::path::PathBuf::default() {
file_diag.map_offsets_to_span(span_map);
needs_error &= !file_diag.has_error();
result.extend(TokenStream::from(file_diag.into_token_stream()))

View file

@ -8,7 +8,7 @@
Please contact info@sixtyfps.io for more information.
LICENSE END */
use std::collections::HashMap;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::rc::Rc;
#[derive(Debug, Clone)]
@ -65,7 +65,32 @@ pub trait Spanned {
}
}
pub type SourceFile = Rc<PathBuf>;
#[derive(Debug, Default)]
pub struct SourceFileInner {
path: PathBuf,
/// Complete source code of the path, used to map from offset to line number
source: Option<String>,
/// The offset of each linebreak
line_offsets: once_cell::unsync::OnceCell<Vec<usize>>,
}
impl SourceFileInner {
pub fn new(path: PathBuf, source: String) -> Self {
Self { path, source: Some(source), line_offsets: Default::default() }
}
pub fn path(&self) -> &Path {
&self.path
}
pub fn from_path(path: PathBuf) -> Rc<Self> {
Rc::new(Self { path, ..Default::default() })
}
}
pub type SourceFile = Rc<SourceFileInner>;
#[derive(Debug, Clone)]
pub struct SourceLocation {
@ -179,11 +204,6 @@ pub struct FileDiagnostics {
pub inner: Vec<Diagnostic>,
/// file path
pub current_path: SourceFile,
/// Complete source code of the path, used to map from offset to line number
pub source: Option<String>,
/// The offset of each linebreak
pub line_offsets: once_cell::unsync::OnceCell<Vec<usize>>,
}
impl IntoIterator for FileDiagnostics {
@ -251,10 +271,10 @@ impl FileDiagnostics {
}
let mut codemap = codemap::CodeMap::new();
let internal_errors = self.source.is_none();
let internal_errors = self.current_path.source.is_none();
let file = codemap.add_file(
self.current_path.to_string_lossy().to_string(),
self.source.unwrap_or_default(),
self.current_path.path.to_string_lossy().to_string(),
self.current_path.source.clone().unwrap_or_default(),
);
let file_span = file.span;
@ -342,17 +362,13 @@ impl FileDiagnostics {
}
pub fn new_from_error(path: std::path::PathBuf, err: std::io::Error) -> Self {
Self {
inner: vec![err.into()],
current_path: Rc::new(path),
source: None,
line_offsets: Default::default(),
}
Self { inner: vec![err.into()], current_path: SourceFileInner::from_path(path) }
}
fn line_offsets(&self) -> &[usize] {
self.line_offsets.get_or_init(|| {
self.source
self.current_path.line_offsets.get_or_init(|| {
self.current_path
.source
.as_ref()
.map(|s| {
s.bytes()
@ -403,34 +419,33 @@ impl quote::ToTokens for FileDiagnostics {
#[derive(Default)]
pub struct BuildDiagnostics {
per_input_file_diagnostics: HashMap<SourceFile, FileDiagnostics>,
per_input_file_diagnostics: HashMap<PathBuf, FileDiagnostics>,
internal_errors: Option<FileDiagnostics>,
}
impl BuildDiagnostics {
pub fn add(&mut self, diagnostics: FileDiagnostics) {
match self.per_input_file_diagnostics.get_mut(&diagnostics.current_path) {
match self.per_input_file_diagnostics.get_mut(&diagnostics.current_path.path) {
Some(existing_diags) => existing_diags.inner.extend(diagnostics.inner),
None => {
self.per_input_file_diagnostics
.insert(diagnostics.current_path.clone(), diagnostics);
.insert(diagnostics.current_path.path.clone(), diagnostics);
}
}
}
fn file_diagnostics(&mut self, source_file: &Rc<PathBuf>) -> &mut FileDiagnostics {
self.per_input_file_diagnostics.entry(source_file.clone()).or_insert_with(|| {
FileDiagnostics { current_path: source_file.clone(), ..Default::default() }
fn file_diagnostics(&mut self, path: &Path) -> &mut FileDiagnostics {
self.per_input_file_diagnostics.entry(path.into()).or_insert_with(|| FileDiagnostics {
current_path: Rc::new(SourceFileInner { path: path.into(), ..Default::default() }),
..Default::default()
})
}
pub fn push_diagnostic(&mut self, message: String, source: &dyn Spanned, level: Level) {
match source.source_file() {
Some(source_file) => self.file_diagnostics(source_file).push_diagnostic_with_span(
message,
source.span(),
level,
),
Some(source_file) => self
.file_diagnostics(source_file.path())
.push_diagnostic_with_span(message, source.span(), level),
None => self.push_internal_error(
CompilerDiagnostic { message, span: source.span(), level }.into(),
),
@ -444,7 +459,10 @@ impl BuildDiagnostics {
pub fn push_internal_error(&mut self, err: Diagnostic) {
self.internal_errors
.get_or_insert_with(|| FileDiagnostics {
current_path: Rc::new("[internal error]".into()),
current_path: Rc::new(SourceFileInner {
path: "[internal error]".into(),
..Default::default()
}),
..Default::default()
})
.inner
@ -458,7 +476,7 @@ impl BuildDiagnostics {
source: &impl Spanned,
) {
self.file_diagnostics(
source.source_file().expect("deprecations cannot be created as internal errors"),
source.source_file().expect("deprecations cannot be created as internal errors").path(),
)
.push_property_deprecation_warning(old_property, new_property, source);
}
@ -488,7 +506,7 @@ impl BuildDiagnostics {
.flat_map(|diag| {
diag.to_string_vec()
.iter()
.map(|err| format!("{}: {}", diag.current_path.to_string_lossy(), err))
.map(|err| format!("{}: {}", diag.current_path.path().to_string_lossy(), err))
.collect::<Vec<_>>()
})
.collect()

View file

@ -297,7 +297,7 @@ impl Spanned for Element {
self.node.as_ref().map(|n| n.span()).unwrap_or_default()
}
fn source_file(&self) -> Option<&Rc<std::path::PathBuf>> {
fn source_file(&self) -> Option<&crate::diagnostics::SourceFile> {
self.node.as_ref().map(|n| n.0.source_file.as_ref()).flatten()
}
}

View file

@ -521,10 +521,8 @@ impl From<Vec<Token>> for DefaultParser {
impl DefaultParser {
/// Constructor that create a parser from the source code
pub fn new(source: String) -> Self {
let mut parser = Self::from(crate::lexer::lex(&source));
parser.diags.source = Some(source);
parser
pub fn new(source: &str) -> Self {
Self::from(crate::lexer::lex(&source))
}
fn current_token(&self) -> Token {
@ -811,10 +809,11 @@ pub fn parse(
source: String,
path: Option<&std::path::Path>,
) -> (SyntaxNodeWithSourceFile, FileDiagnostics) {
let mut p = DefaultParser::new(source);
let mut p = DefaultParser::new(&source);
document::parse_document(&mut p);
let source_file = if let Some(path) = path {
p.diags.current_path = std::rc::Rc::new(path.to_path_buf());
p.diags.current_path =
std::rc::Rc::new(crate::diagnostics::SourceFileInner::new(path.to_path_buf(), source));
Some(p.diags.current_path.clone())
} else {
None

View file

@ -411,10 +411,7 @@ impl Expression {
ctx.type_loader
.and_then(|loader| {
loader
.import_file(
node.source_file.as_ref().map(|path_rc| path_rc.as_path()),
&s,
)
.import_file(node.source_file.as_ref().map(|sf| sf.path()), &s)
.map(|resolved_file| resolved_file.path)
})
.unwrap_or_else(|| {

View file

@ -158,10 +158,10 @@ fn process_file_source(
let mut success = true;
for diagnostics in compile_diagnostics.into_iter() {
let source = if *diagnostics.current_path == path {
let source = if diagnostics.current_path.path() == path {
source.clone()
} else {
std::fs::read_to_string(diagnostics.current_path.as_ref())?
std::fs::read_to_string(diagnostics.current_path.path())?
};
success &= process_diagnostics(diagnostics, source, silent)?;
}

View file

@ -14,7 +14,7 @@ use std::io::Read;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use crate::diagnostics::{BuildDiagnostics, CompilerDiagnostic, FileDiagnostics, SourceFile};
use crate::diagnostics::{BuildDiagnostics, CompilerDiagnostic, FileDiagnostics};
use crate::object_tree::{self, Document};
use crate::parser::{syntax_nodes, SyntaxKind, SyntaxTokenWithSourceFile};
use crate::typeregister::TypeRegister;
@ -234,13 +234,7 @@ impl<'a> TypeLoader<'a> {
}
};
self.load_file(
&path_canon,
SourceFile::new(path.to_owned()),
source_code,
build_diagnostics,
)
.await;
self.load_file(&path_canon, path, source_code, build_diagnostics).await;
let _ok = self.all_documents.currently_loading.remove(path_canon.as_path());
assert!(_ok);
Some(path_canon)
@ -252,15 +246,13 @@ impl<'a> TypeLoader<'a> {
pub async fn load_file(
&mut self,
path: &Path,
source_path: SourceFile,
source_path: &Path,
source_code: String,
build_diagnostics: &mut BuildDiagnostics,
) {
let (dependency_doc, mut dependency_diagnostics) =
crate::parser::parse(source_code, Some(&source_path));
dependency_diagnostics.current_path = source_path;
if dependency_diagnostics.has_error() {
build_diagnostics.add(dependency_diagnostics);
let mut d = Document::default();
@ -401,7 +393,7 @@ impl<'a> TypeLoader<'a> {
doc: &syntax_nodes::Document,
doc_diagnostics: &mut FileDiagnostics,
) -> impl Iterator<Item = ImportedTypes> {
let referencing_file = doc.source_file.as_ref().unwrap().clone();
let referencing_file = doc.source_file.as_ref().unwrap().path().clone();
let mut dependencies = DependenciesByFile::new();

View file

@ -194,22 +194,17 @@ fn reload_document(
let path = Path::new(uri.path());
let path_canon = path.canonicalize().unwrap_or_else(|_| path.to_owned());
let mut diag = BuildDiagnostics::default();
spin_on::spin_on(document_cache.documents.load_file(
&path_canon,
sixtyfps_compilerlib::diagnostics::SourceFile::new(path.to_owned()),
content,
&mut diag,
));
spin_on::spin_on(document_cache.documents.load_file(&path_canon, path, content, &mut diag));
for file_diag in diag.into_iter() {
if file_diag.current_path.is_relative() {
if file_diag.current_path.path().is_relative() {
continue;
}
let diagnostics = file_diag.inner.iter().map(|d| to_lsp_diag(d, &file_diag)).collect();
connection.sender.send(Message::Notification(lsp_server::Notification::new(
"textDocument/publishDiagnostics".into(),
PublishDiagnosticsParams {
uri: Url::from_file_path(file_diag.current_path.as_path()).unwrap(),
uri: Url::from_file_path(file_diag.current_path.path()).unwrap(),
diagnostics,
version: None,
},
@ -272,7 +267,7 @@ fn goto_definition(
sixtyfps_compilerlib::object_tree::QualifiedTypeName::from_node(token.into());
match parent.kind() {
SyntaxKind::Element => {
let doc = document_cache.documents.get_document(source_file.as_path())?;
let doc = document_cache.documents.get_document(source_file.path())?;
match doc.local_registry.lookup_qualified(&qual.members) {
sixtyfps_compilerlib::langtype::Type::Component(c) => {
goto_node(document_cache, &c.root_element.borrow().node.as_ref()?.0)
@ -291,7 +286,7 @@ fn goto_node(
document_cache: &mut DocumentCache,
node: &SyntaxNodeWithSourceFile,
) -> Option<GotoDefinitionResponse> {
let path = node.source_file.as_ref()?.as_path();
let path = node.source_file.as_ref()?.path();
let target_uri = Url::from_file_path(path).ok()?;
let newline_offsets = match document_cache.newline_offsets.entry(target_uri.clone()) {
std::collections::hash_map::Entry::Occupied(e) => e.into_mut(),