mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 06:11:16 +00:00
Put what is the FileDiagnostics into the SourceFile so the SourceFile has the content
This commit is contained in:
parent
7c48bcdd4c
commit
968dfaae87
8 changed files with 70 additions and 70 deletions
|
@ -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 source_file = if let Some(cargo_manifest) = std::env::var_os("CARGO_MANIFEST_DIR") {
|
||||||
let mut path: std::path::PathBuf = cargo_manifest.into();
|
let mut path: std::path::PathBuf = cargo_manifest.into();
|
||||||
path.push("Cargo.toml");
|
path.push("Cargo.toml");
|
||||||
diag.current_path = std::rc::Rc::new(path);
|
Some(diagnostics::SourceFileInner::from_path(path))
|
||||||
Some(diag.current_path.clone())
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -371,7 +370,7 @@ fn report_diagnostics(
|
||||||
let mut result = TokenStream::new();
|
let mut result = TokenStream::new();
|
||||||
let mut needs_error = diag.has_error();
|
let mut needs_error = diag.has_error();
|
||||||
for mut file_diag in diag.into_iter() {
|
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);
|
file_diag.map_offsets_to_span(span_map);
|
||||||
needs_error &= !file_diag.has_error();
|
needs_error &= !file_diag.has_error();
|
||||||
result.extend(TokenStream::from(file_diag.into_token_stream()))
|
result.extend(TokenStream::from(file_diag.into_token_stream()))
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
Please contact info@sixtyfps.io for more information.
|
Please contact info@sixtyfps.io for more information.
|
||||||
LICENSE END */
|
LICENSE END */
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SourceLocation {
|
pub struct SourceLocation {
|
||||||
|
@ -179,11 +204,6 @@ pub struct FileDiagnostics {
|
||||||
pub inner: Vec<Diagnostic>,
|
pub inner: Vec<Diagnostic>,
|
||||||
/// file path
|
/// file path
|
||||||
pub current_path: SourceFile,
|
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 {
|
impl IntoIterator for FileDiagnostics {
|
||||||
|
@ -251,10 +271,10 @@ impl FileDiagnostics {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut codemap = codemap::CodeMap::new();
|
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(
|
let file = codemap.add_file(
|
||||||
self.current_path.to_string_lossy().to_string(),
|
self.current_path.path.to_string_lossy().to_string(),
|
||||||
self.source.unwrap_or_default(),
|
self.current_path.source.clone().unwrap_or_default(),
|
||||||
);
|
);
|
||||||
let file_span = file.span;
|
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 {
|
pub fn new_from_error(path: std::path::PathBuf, err: std::io::Error) -> Self {
|
||||||
Self {
|
Self { inner: vec![err.into()], current_path: SourceFileInner::from_path(path) }
|
||||||
inner: vec![err.into()],
|
|
||||||
current_path: Rc::new(path),
|
|
||||||
source: None,
|
|
||||||
line_offsets: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn line_offsets(&self) -> &[usize] {
|
fn line_offsets(&self) -> &[usize] {
|
||||||
self.line_offsets.get_or_init(|| {
|
self.current_path.line_offsets.get_or_init(|| {
|
||||||
self.source
|
self.current_path
|
||||||
|
.source
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| {
|
.map(|s| {
|
||||||
s.bytes()
|
s.bytes()
|
||||||
|
@ -403,34 +419,33 @@ impl quote::ToTokens for FileDiagnostics {
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct BuildDiagnostics {
|
pub struct BuildDiagnostics {
|
||||||
per_input_file_diagnostics: HashMap<SourceFile, FileDiagnostics>,
|
per_input_file_diagnostics: HashMap<PathBuf, FileDiagnostics>,
|
||||||
internal_errors: Option<FileDiagnostics>,
|
internal_errors: Option<FileDiagnostics>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuildDiagnostics {
|
impl BuildDiagnostics {
|
||||||
pub fn add(&mut self, diagnostics: FileDiagnostics) {
|
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),
|
Some(existing_diags) => existing_diags.inner.extend(diagnostics.inner),
|
||||||
None => {
|
None => {
|
||||||
self.per_input_file_diagnostics
|
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 {
|
fn file_diagnostics(&mut self, path: &Path) -> &mut FileDiagnostics {
|
||||||
self.per_input_file_diagnostics.entry(source_file.clone()).or_insert_with(|| {
|
self.per_input_file_diagnostics.entry(path.into()).or_insert_with(|| FileDiagnostics {
|
||||||
FileDiagnostics { current_path: source_file.clone(), ..Default::default() }
|
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) {
|
pub fn push_diagnostic(&mut self, message: String, source: &dyn Spanned, level: Level) {
|
||||||
match source.source_file() {
|
match source.source_file() {
|
||||||
Some(source_file) => self.file_diagnostics(source_file).push_diagnostic_with_span(
|
Some(source_file) => self
|
||||||
message,
|
.file_diagnostics(source_file.path())
|
||||||
source.span(),
|
.push_diagnostic_with_span(message, source.span(), level),
|
||||||
level,
|
|
||||||
),
|
|
||||||
None => self.push_internal_error(
|
None => self.push_internal_error(
|
||||||
CompilerDiagnostic { message, span: source.span(), level }.into(),
|
CompilerDiagnostic { message, span: source.span(), level }.into(),
|
||||||
),
|
),
|
||||||
|
@ -444,7 +459,10 @@ impl BuildDiagnostics {
|
||||||
pub fn push_internal_error(&mut self, err: Diagnostic) {
|
pub fn push_internal_error(&mut self, err: Diagnostic) {
|
||||||
self.internal_errors
|
self.internal_errors
|
||||||
.get_or_insert_with(|| FileDiagnostics {
|
.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()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.inner
|
.inner
|
||||||
|
@ -458,7 +476,7 @@ impl BuildDiagnostics {
|
||||||
source: &impl Spanned,
|
source: &impl Spanned,
|
||||||
) {
|
) {
|
||||||
self.file_diagnostics(
|
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);
|
.push_property_deprecation_warning(old_property, new_property, source);
|
||||||
}
|
}
|
||||||
|
@ -488,7 +506,7 @@ impl BuildDiagnostics {
|
||||||
.flat_map(|diag| {
|
.flat_map(|diag| {
|
||||||
diag.to_string_vec()
|
diag.to_string_vec()
|
||||||
.iter()
|
.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::<Vec<_>>()
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|
|
@ -297,7 +297,7 @@ impl Spanned for Element {
|
||||||
self.node.as_ref().map(|n| n.span()).unwrap_or_default()
|
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()
|
self.node.as_ref().map(|n| n.0.source_file.as_ref()).flatten()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -521,10 +521,8 @@ impl From<Vec<Token>> for DefaultParser {
|
||||||
|
|
||||||
impl DefaultParser {
|
impl DefaultParser {
|
||||||
/// Constructor that create a parser from the source code
|
/// Constructor that create a parser from the source code
|
||||||
pub fn new(source: String) -> Self {
|
pub fn new(source: &str) -> Self {
|
||||||
let mut parser = Self::from(crate::lexer::lex(&source));
|
Self::from(crate::lexer::lex(&source))
|
||||||
parser.diags.source = Some(source);
|
|
||||||
parser
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn current_token(&self) -> Token {
|
fn current_token(&self) -> Token {
|
||||||
|
@ -811,10 +809,11 @@ pub fn parse(
|
||||||
source: String,
|
source: String,
|
||||||
path: Option<&std::path::Path>,
|
path: Option<&std::path::Path>,
|
||||||
) -> (SyntaxNodeWithSourceFile, FileDiagnostics) {
|
) -> (SyntaxNodeWithSourceFile, FileDiagnostics) {
|
||||||
let mut p = DefaultParser::new(source);
|
let mut p = DefaultParser::new(&source);
|
||||||
document::parse_document(&mut p);
|
document::parse_document(&mut p);
|
||||||
let source_file = if let Some(path) = path {
|
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())
|
Some(p.diags.current_path.clone())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -411,10 +411,7 @@ impl Expression {
|
||||||
ctx.type_loader
|
ctx.type_loader
|
||||||
.and_then(|loader| {
|
.and_then(|loader| {
|
||||||
loader
|
loader
|
||||||
.import_file(
|
.import_file(node.source_file.as_ref().map(|sf| sf.path()), &s)
|
||||||
node.source_file.as_ref().map(|path_rc| path_rc.as_path()),
|
|
||||||
&s,
|
|
||||||
)
|
|
||||||
.map(|resolved_file| resolved_file.path)
|
.map(|resolved_file| resolved_file.path)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
|
|
|
@ -158,10 +158,10 @@ fn process_file_source(
|
||||||
let mut success = true;
|
let mut success = true;
|
||||||
|
|
||||||
for diagnostics in compile_diagnostics.into_iter() {
|
for diagnostics in compile_diagnostics.into_iter() {
|
||||||
let source = if *diagnostics.current_path == path {
|
let source = if diagnostics.current_path.path() == path {
|
||||||
source.clone()
|
source.clone()
|
||||||
} else {
|
} 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)?;
|
success &= process_diagnostics(diagnostics, source, silent)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
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::object_tree::{self, Document};
|
||||||
use crate::parser::{syntax_nodes, SyntaxKind, SyntaxTokenWithSourceFile};
|
use crate::parser::{syntax_nodes, SyntaxKind, SyntaxTokenWithSourceFile};
|
||||||
use crate::typeregister::TypeRegister;
|
use crate::typeregister::TypeRegister;
|
||||||
|
@ -234,13 +234,7 @@ impl<'a> TypeLoader<'a> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.load_file(
|
self.load_file(&path_canon, path, source_code, build_diagnostics).await;
|
||||||
&path_canon,
|
|
||||||
SourceFile::new(path.to_owned()),
|
|
||||||
source_code,
|
|
||||||
build_diagnostics,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
let _ok = self.all_documents.currently_loading.remove(path_canon.as_path());
|
let _ok = self.all_documents.currently_loading.remove(path_canon.as_path());
|
||||||
assert!(_ok);
|
assert!(_ok);
|
||||||
Some(path_canon)
|
Some(path_canon)
|
||||||
|
@ -252,15 +246,13 @@ impl<'a> TypeLoader<'a> {
|
||||||
pub async fn load_file(
|
pub async fn load_file(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
source_path: SourceFile,
|
source_path: &Path,
|
||||||
source_code: String,
|
source_code: String,
|
||||||
build_diagnostics: &mut BuildDiagnostics,
|
build_diagnostics: &mut BuildDiagnostics,
|
||||||
) {
|
) {
|
||||||
let (dependency_doc, mut dependency_diagnostics) =
|
let (dependency_doc, mut dependency_diagnostics) =
|
||||||
crate::parser::parse(source_code, Some(&source_path));
|
crate::parser::parse(source_code, Some(&source_path));
|
||||||
|
|
||||||
dependency_diagnostics.current_path = source_path;
|
|
||||||
|
|
||||||
if dependency_diagnostics.has_error() {
|
if dependency_diagnostics.has_error() {
|
||||||
build_diagnostics.add(dependency_diagnostics);
|
build_diagnostics.add(dependency_diagnostics);
|
||||||
let mut d = Document::default();
|
let mut d = Document::default();
|
||||||
|
@ -401,7 +393,7 @@ impl<'a> TypeLoader<'a> {
|
||||||
doc: &syntax_nodes::Document,
|
doc: &syntax_nodes::Document,
|
||||||
doc_diagnostics: &mut FileDiagnostics,
|
doc_diagnostics: &mut FileDiagnostics,
|
||||||
) -> impl Iterator<Item = ImportedTypes> {
|
) -> 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();
|
let mut dependencies = DependenciesByFile::new();
|
||||||
|
|
||||||
|
|
|
@ -194,22 +194,17 @@ fn reload_document(
|
||||||
let path = Path::new(uri.path());
|
let path = Path::new(uri.path());
|
||||||
let path_canon = path.canonicalize().unwrap_or_else(|_| path.to_owned());
|
let path_canon = path.canonicalize().unwrap_or_else(|_| path.to_owned());
|
||||||
let mut diag = BuildDiagnostics::default();
|
let mut diag = BuildDiagnostics::default();
|
||||||
spin_on::spin_on(document_cache.documents.load_file(
|
spin_on::spin_on(document_cache.documents.load_file(&path_canon, path, content, &mut diag));
|
||||||
&path_canon,
|
|
||||||
sixtyfps_compilerlib::diagnostics::SourceFile::new(path.to_owned()),
|
|
||||||
content,
|
|
||||||
&mut diag,
|
|
||||||
));
|
|
||||||
|
|
||||||
for file_diag in diag.into_iter() {
|
for file_diag in diag.into_iter() {
|
||||||
if file_diag.current_path.is_relative() {
|
if file_diag.current_path.path().is_relative() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let diagnostics = file_diag.inner.iter().map(|d| to_lsp_diag(d, &file_diag)).collect();
|
let diagnostics = file_diag.inner.iter().map(|d| to_lsp_diag(d, &file_diag)).collect();
|
||||||
connection.sender.send(Message::Notification(lsp_server::Notification::new(
|
connection.sender.send(Message::Notification(lsp_server::Notification::new(
|
||||||
"textDocument/publishDiagnostics".into(),
|
"textDocument/publishDiagnostics".into(),
|
||||||
PublishDiagnosticsParams {
|
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,
|
diagnostics,
|
||||||
version: None,
|
version: None,
|
||||||
},
|
},
|
||||||
|
@ -272,7 +267,7 @@ fn goto_definition(
|
||||||
sixtyfps_compilerlib::object_tree::QualifiedTypeName::from_node(token.into());
|
sixtyfps_compilerlib::object_tree::QualifiedTypeName::from_node(token.into());
|
||||||
match parent.kind() {
|
match parent.kind() {
|
||||||
SyntaxKind::Element => {
|
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) {
|
match doc.local_registry.lookup_qualified(&qual.members) {
|
||||||
sixtyfps_compilerlib::langtype::Type::Component(c) => {
|
sixtyfps_compilerlib::langtype::Type::Component(c) => {
|
||||||
goto_node(document_cache, &c.root_element.borrow().node.as_ref()?.0)
|
goto_node(document_cache, &c.root_element.borrow().node.as_ref()?.0)
|
||||||
|
@ -291,7 +286,7 @@ fn goto_node(
|
||||||
document_cache: &mut DocumentCache,
|
document_cache: &mut DocumentCache,
|
||||||
node: &SyntaxNodeWithSourceFile,
|
node: &SyntaxNodeWithSourceFile,
|
||||||
) -> Option<GotoDefinitionResponse> {
|
) -> 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 target_uri = Url::from_file_path(path).ok()?;
|
||||||
let newline_offsets = match document_cache.newline_offsets.entry(target_uri.clone()) {
|
let newline_offsets = match document_cache.newline_offsets.entry(target_uri.clone()) {
|
||||||
std::collections::hash_map::Entry::Occupied(e) => e.into_mut(),
|
std::collections::hash_map::Entry::Occupied(e) => e.into_mut(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue