Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 68 additions & 65 deletions crates/ty_project/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,11 @@ impl Project {
tracing::debug_span!(parent: project_span, "check_file", ?file);
let _entered = check_file_span.entered();

let result = self.check_file_impl(&db, file);
file_diagnostics.lock().unwrap().extend(result);
let result = check_file_impl(&db, file);
file_diagnostics
.lock()
.unwrap()
.extend(result.iter().map(Clone::clone));

reporter.report_file(&file);
});
Expand All @@ -285,7 +288,7 @@ impl Project {
return Vec::new();
}

self.check_file_impl(db, file)
check_file_impl(db, file).iter().map(Clone::clone).collect()
}

/// Opens a file in the project.
Expand Down Expand Up @@ -466,71 +469,73 @@ impl Project {
self.set_file_set(db).to(IndexedFiles::lazy());
}
}
}

fn check_file_impl(self, db: &dyn Db, file: File) -> Vec<Diagnostic> {
let mut diagnostics: Vec<Diagnostic> = Vec::new();

// Abort checking if there are IO errors.
let source = source_text(db, file);

if let Some(read_error) = source.read_error() {
diagnostics.push(
IOErrorDiagnostic {
file: Some(file),
error: read_error.clone().into(),
}
.to_diagnostic(),
);
return diagnostics;
}
#[salsa::tracked(returns(deref), heap_size=get_size2::GetSize::get_heap_size)]
pub(crate) fn check_file_impl(db: &dyn Db, file: File) -> Box<[Diagnostic]> {
let mut diagnostics: Vec<Diagnostic> = Vec::new();

let parsed = parsed_module(db, file);
// Abort checking if there are IO errors.
let source = source_text(db, file);

let parsed_ref = parsed.load(db);
diagnostics.extend(
parsed_ref
.errors()
.iter()
.map(|error| Diagnostic::invalid_syntax(file, &error.error, error)),
if let Some(read_error) = source.read_error() {
diagnostics.push(
IOErrorDiagnostic {
file: Some(file),
error: read_error.clone().into(),
}
.to_diagnostic(),
);
return diagnostics.into_boxed_slice();
}

diagnostics.extend(parsed_ref.unsupported_syntax_errors().iter().map(|error| {
let mut error = Diagnostic::invalid_syntax(file, error, error);
add_inferred_python_version_hint_to_diagnostic(db, &mut error, "parsing syntax");
error
}));

{
let db = AssertUnwindSafe(db);
match catch(&**db, file, || check_types(*db, file)) {
Ok(Some(type_check_diagnostics)) => {
diagnostics.extend(type_check_diagnostics.into_iter().cloned());
}
Ok(None) => {}
Err(diagnostic) => diagnostics.push(diagnostic),
let parsed = parsed_module(db, file);

let parsed_ref = parsed.load(db);
diagnostics.extend(
parsed_ref
.errors()
.iter()
.map(|error| Diagnostic::invalid_syntax(file, &error.error, error)),
);

diagnostics.extend(parsed_ref.unsupported_syntax_errors().iter().map(|error| {
let mut error = Diagnostic::invalid_syntax(file, error, error);
add_inferred_python_version_hint_to_diagnostic(db, &mut error, "parsing syntax");
error
}));

{
let db = AssertUnwindSafe(db);
match catch(&**db, file, || check_types(*db, file)) {
Ok(Some(type_check_diagnostics)) => {
diagnostics.extend(type_check_diagnostics);
}
Ok(None) => {}
Err(diagnostic) => diagnostics.push(diagnostic),
}
}

if self
.open_fileset(db)
.is_none_or(|files| !files.contains(&file))
{
// Drop the AST now that we are done checking this file. It is not currently open,
// so it is unlikely to be accessed again soon. If any queries need to access the AST
// from across files, it will be re-parsed.
parsed.clear();
}
if db
.project()
.open_fileset(db)
.is_none_or(|files| !files.contains(&file))
{
// Drop the AST now that we are done checking this file. It is not currently open,
// so it is unlikely to be accessed again soon. If any queries need to access the AST
// from across files, it will be re-parsed.
parsed.clear();
}

diagnostics.sort_unstable_by_key(|diagnostic| {
diagnostic
.primary_span()
.and_then(|span| span.range())
.unwrap_or_default()
.start()
});
diagnostics.sort_unstable_by_key(|diagnostic| {
diagnostic
.primary_span()
.and_then(|span| span.range())
.unwrap_or_default()
.start()
});

diagnostics
}
diagnostics.into_boxed_slice()
}

#[derive(Debug)]
Expand Down Expand Up @@ -701,8 +706,8 @@ where

#[cfg(test)]
mod tests {
use crate::Db;
use crate::ProjectMetadata;
use crate::check_file_impl;
use crate::db::tests::TestDb;
use ruff_db::Db as _;
use ruff_db::files::system_path_to_file;
Expand Down Expand Up @@ -741,9 +746,8 @@ mod tests {

assert_eq!(source_text(&db, file).as_str(), "");
assert_eq!(
db.project()
.check_file_impl(&db, file)
.into_iter()
check_file_impl(&db, file)
.iter()
.map(|diagnostic| diagnostic.primary_message().to_string())
.collect::<Vec<_>>(),
vec!["Failed to read file: No such file or directory".to_string()]
Expand All @@ -758,9 +762,8 @@ mod tests {

assert_eq!(source_text(&db, file).as_str(), "");
assert_eq!(
db.project()
.check_file_impl(&db, file)
.into_iter()
check_file_impl(&db, file)
.iter()
.map(|diagnostic| diagnostic.primary_message().to_string())
.collect::<Vec<_>>(),
vec![] as Vec<String>
Expand Down
5 changes: 2 additions & 3 deletions crates/ty_python_semantic/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ mod definition;
#[cfg(test)]
mod property_tests;

#[salsa::tracked(returns(ref), heap_size=get_size2::GetSize::get_heap_size)]
pub fn check_types(db: &dyn Db, file: File) -> TypeCheckDiagnostics {
pub fn check_types(db: &dyn Db, file: File) -> Vec<Diagnostic> {
let _span = tracing::trace_span!("check_types", ?file).entered();

tracing::debug!("Checking file '{path}'", path = file.path(db));
Expand All @@ -111,7 +110,7 @@ pub fn check_types(db: &dyn Db, file: File) -> TypeCheckDiagnostics {

check_suppressions(db, file, &mut diagnostics);

diagnostics
diagnostics.into_vec()
}

/// Infer the type of a binding.
Expand Down
4 changes: 4 additions & 0 deletions crates/ty_python_semantic/src/types/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,10 @@ impl TypeCheckDiagnostics {
self.diagnostics.shrink_to_fit();
}

pub(crate) fn into_vec(self) -> Vec<Diagnostic> {
self.diagnostics
}

pub fn iter(&self) -> std::slice::Iter<'_, Diagnostic> {
self.diagnostics.iter()
}
Expand Down
4 changes: 2 additions & 2 deletions crates/ty_python_semantic/src/types/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10035,7 +10035,7 @@ mod tests {
}

#[track_caller]
fn assert_diagnostic_messages(diagnostics: &TypeCheckDiagnostics, expected: &[&str]) {
fn assert_diagnostic_messages(diagnostics: &[Diagnostic], expected: &[&str]) {
let messages: Vec<&str> = diagnostics
.iter()
.map(Diagnostic::primary_message)
Expand All @@ -10048,7 +10048,7 @@ mod tests {
let file = system_path_to_file(db, filename).unwrap();
let diagnostics = check_types(db, file);

assert_diagnostic_messages(diagnostics, expected);
assert_diagnostic_messages(&diagnostics, expected);
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion crates/ty_test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ fn run_test(
Err(failures) => return Some(failures),
};

diagnostics.extend(type_diagnostics.into_iter().cloned());
diagnostics.extend(type_diagnostics);
diagnostics.sort_by(|left, right| {
left.rendering_sort_key(db)
.cmp(&right.rendering_sort_key(db))
Expand Down
Loading