From 02b4c1fa857e4f0c9b1f791801e30f6f9074d5a5 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Tue, 26 Aug 2025 11:56:53 +0200 Subject: [PATCH 1/3] Rust: downgrade uncompiled source files from warning to info --- rust/extractor/src/main.rs | 42 ++++++++++--------- rust/extractor/src/rust_analyzer.rs | 63 ++++++++++++++++++++++++----- rust/extractor/src/trap.rs | 3 +- 3 files changed, 78 insertions(+), 30 deletions(-) diff --git a/rust/extractor/src/main.rs b/rust/extractor/src/main.rs index 1c8629cbbb90..27f0082fb6ad 100644 --- a/rust/extractor/src/main.rs +++ b/rust/extractor/src/main.rs @@ -1,5 +1,5 @@ use crate::diagnostics::{ExtractionStep, emit_extraction_diagnostics}; -use crate::rust_analyzer::path_to_file_id; +use crate::rust_analyzer::{RustAnalyzerNoSemantics, path_to_file_id}; use crate::translate::{ResolvePaths, SourceKind}; use crate::trap::TrapId; use anyhow::Context; @@ -87,14 +87,12 @@ impl<'a> Extractor<'a> { translator.emit_parse_error(&ast, &err); } let no_location = (LineCol { line: 0, col: 0 }, LineCol { line: 0, col: 0 }); - if let Err(reason) = semantics_info { + if let Err(RustAnalyzerNoSemantics { severity, reason }) = semantics_info { if !reason.is_empty() { let message = format!("semantic analyzer unavailable ({reason})"); - let full_message = format!( - "{message}: macro expansion, call graph, and type inference will be skipped." - ); + let full_message = format!("{message}: macro expansion will be skipped."); translator.emit_diagnostic( - trap::DiagnosticSeverity::Warning, + severity, "semantics".to_owned(), message, full_message, @@ -135,10 +133,10 @@ impl<'a> Extractor<'a> { &mut self, file: &Path, source_kind: SourceKind, - reason: &str, + err: RustAnalyzerNoSemantics, ) { self.extract( - &RustAnalyzer::WithoutSemantics { reason }, + &RustAnalyzer::from(err), file, ResolvePaths::No, source_kind, @@ -163,21 +161,25 @@ impl<'a> Extractor<'a> { file: &Path, semantics: &Semantics<'_, RootDatabase>, vfs: &Vfs, - ) -> Result<(), String> { + ) -> Result<(), RustAnalyzerNoSemantics> { let before = Instant::now(); let Some(id) = path_to_file_id(file, vfs) else { - return Err("not included in files loaded from manifest".to_string()); + return Err(RustAnalyzerNoSemantics::warning( + "not included in files loaded from manifest", + )); }; match semantics.file_to_module_def(id) { - None => return Err("not included as a module".to_string()), + None => { + return Err(RustAnalyzerNoSemantics::info("not included as a module")); + } Some(module) if module .as_source_file_id(semantics.db) .is_none_or(|mod_file_id| mod_file_id.file_id(semantics.db) != id) => { - return Err( - "not loaded as its own module, probably included by `!include`".to_string(), - ); + return Err(RustAnalyzerNoSemantics::info( + "not loaded as its own module, probably included by `!include`", + )); } _ => {} }; @@ -279,7 +281,11 @@ fn main() -> anyhow::Result<()> { continue 'outer; } } - extractor.extract_without_semantics(file, SourceKind::Source, "no manifest found"); + extractor.extract_without_semantics( + file, + SourceKind::Source, + RustAnalyzerNoSemantics::warning("no manifest found"), + ); } let cwd = cwd()?; let (cargo_config, load_cargo_config) = cfg.to_cargo_config(&cwd); @@ -319,7 +325,7 @@ fn main() -> anyhow::Result<()> { source_resolve_paths, source_mode, ), - Err(reason) => extractor.extract_without_semantics(file, source_mode, &reason), + Err(e) => extractor.extract_without_semantics(file, source_mode, e), }; } for (file_id, file) in vfs.iter() { @@ -347,7 +353,7 @@ fn main() -> anyhow::Result<()> { extractor.extract_without_semantics( file, SourceKind::Source, - "unable to load manifest", + RustAnalyzerNoSemantics::warning("unable to load manifest"), ); } } @@ -359,7 +365,7 @@ fn main() -> anyhow::Result<()> { let entry = entry.context("failed to read builtins directory")?; let path = entry.path(); if path.extension().is_some_and(|ext| ext == "rs") { - extractor.extract_without_semantics(&path, SourceKind::Library, ""); + extractor.extract_without_semantics(&path, SourceKind::Library, Default::default()); } } diff --git a/rust/extractor/src/rust_analyzer.rs b/rust/extractor/src/rust_analyzer.rs index ce9d763db4d0..9d3769a24040 100644 --- a/rust/extractor/src/rust_analyzer.rs +++ b/rust/extractor/src/rust_analyzer.rs @@ -1,3 +1,4 @@ +use crate::trap; use itertools::Itertools; use ra_ap_base_db::{EditionedFileId, FileText, RootQueryDb, SourceDatabase}; use ra_ap_hir::Semantics; @@ -23,16 +24,47 @@ use std::rc::Rc; use tracing::{debug, error, info, trace, warn}; use triomphe::Arc; +#[derive(Clone, Default)] +pub struct RustAnalyzerNoSemantics { + pub severity: trap::DiagnosticSeverity, + pub reason: &'static str, +} + +impl RustAnalyzerNoSemantics { + pub fn warning(reason: &'static str) -> Self { + RustAnalyzerNoSemantics { + severity: trap::DiagnosticSeverity::Warning, + reason, + } + } + pub fn info(reason: &'static str) -> Self { + RustAnalyzerNoSemantics { + severity: trap::DiagnosticSeverity::Info, + reason, + } + } +} + pub enum RustAnalyzer<'a> { WithSemantics { vfs: &'a Vfs, semantics: &'a Semantics<'a, RootDatabase>, }, WithoutSemantics { - reason: &'a str, + severity: trap::DiagnosticSeverity, + reason: &'static str, }, } +impl From for RustAnalyzer<'static> { + fn from(value: RustAnalyzerNoSemantics) -> Self { + RustAnalyzer::WithoutSemantics { + severity: value.severity, + reason: value.reason, + } + } +} + pub struct FileSemanticInformation<'a> { pub file_id: EditionedFileId, pub semantics: &'a Semantics<'a, RootDatabase>, @@ -42,7 +74,7 @@ pub struct ParseResult<'a> { pub ast: SourceFile, pub text: Arc, pub errors: Vec, - pub semantics_info: Result, &'a str>, + pub semantics_info: Result, RustAnalyzerNoSemantics>, } impl<'a> RustAnalyzer<'a> { @@ -52,7 +84,7 @@ impl<'a> RustAnalyzer<'a> { load_config: &LoadCargoConfig, ) -> Option<(RootDatabase, Vfs)> { let progress = |t| trace!("progress: {t}"); - let manifest = project.manifest_path(); + let manifest: &ManifestPath = project.manifest_path(); match load_workspace_at(manifest.as_ref(), config, load_config, &progress) { Ok((db, vfs, _macro_server)) => Some((db, vfs)), Err(err) => { @@ -67,16 +99,25 @@ impl<'a> RustAnalyzer<'a> { fn get_file_data( &self, path: &Path, - ) -> Result<(&Semantics<'_, RootDatabase>, EditionedFileId, FileText), &str> { + ) -> Result<(&Semantics<'_, RootDatabase>, EditionedFileId, FileText), RustAnalyzerNoSemantics> + { match self { - RustAnalyzer::WithoutSemantics { reason } => Err(reason), + RustAnalyzer::WithoutSemantics { severity, reason } => Err(RustAnalyzerNoSemantics { + severity: *severity, + reason, + }), RustAnalyzer::WithSemantics { vfs, semantics } => { - let file_id = path_to_file_id(path, vfs).ok_or("file not found in project")?; - let input = std::panic::catch_unwind(|| semantics.db.file_text(file_id)) - .or(Err("no text available for the file in the project"))?; - let editioned_file_id = semantics - .attach_first_edition(file_id) - .ok_or("failed to determine rust edition")?; + let file_id = path_to_file_id(path, vfs).ok_or( + RustAnalyzerNoSemantics::warning("file not found in project"), + )?; + let input = std::panic::catch_unwind(|| semantics.db.file_text(file_id)).or( + Err(RustAnalyzerNoSemantics::warning( + "no text available for the file in the project", + )), + )?; + let editioned_file_id = semantics.attach_first_edition(file_id).ok_or( + RustAnalyzerNoSemantics::warning("failed to determine rust edition"), + )?; Ok((semantics, editioned_file_id, input)) } } diff --git a/rust/extractor/src/trap.rs b/rust/extractor/src/trap.rs index 3a6dbeb24e11..31e9f2122d70 100644 --- a/rust/extractor/src/trap.rs +++ b/rust/extractor/src/trap.rs @@ -127,9 +127,10 @@ pub struct TrapFile { compression: Compression, } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)] pub enum DiagnosticSeverity { Debug = 10, + #[default] Info = 20, Warning = 30, Error = 40, From 999920c9681859ea196b83ec85a3db992f70792b Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Tue, 26 Aug 2025 12:30:27 +0200 Subject: [PATCH 2/3] Rust: accept test changes --- .../hello-project/ExtractionWarnings.expected | 1 - rust/ql/integration-tests/hello-project/summary.expected | 8 ++++---- .../CONSISTENCY/ExtractionConsistency.expected | 1 - .../ql/test/extractor-tests/macro-expansion/test.expected | 1 - .../CONSISTENCY/ExtractionConsistency.expected | 2 -- .../CONSISTENCY/ExtractionConsistency.expected | 2 -- 6 files changed, 4 insertions(+), 11 deletions(-) delete mode 100644 rust/ql/test/library-tests/type-inference/CONSISTENCY/ExtractionConsistency.expected delete mode 100644 rust/ql/test/query-tests/unusedentities/CONSISTENCY/ExtractionConsistency.expected diff --git a/rust/ql/integration-tests/hello-project/ExtractionWarnings.expected b/rust/ql/integration-tests/hello-project/ExtractionWarnings.expected index ef3e107fa760..e69de29bb2d1 100644 --- a/rust/ql/integration-tests/hello-project/ExtractionWarnings.expected +++ b/rust/ql/integration-tests/hello-project/ExtractionWarnings.expected @@ -1 +0,0 @@ -| src/directory_module/not_loaded.rs:1:1:1:1 | semantic analyzer unavailable (not included as a module) | Extraction warning in src/directory_module/not_loaded.rs with message semantic analyzer unavailable (not included as a module) | 1 | diff --git a/rust/ql/integration-tests/hello-project/summary.expected b/rust/ql/integration-tests/hello-project/summary.expected index 1f343b197c0f..0d639fe44f75 100644 --- a/rust/ql/integration-tests/hello-project/summary.expected +++ b/rust/ql/integration-tests/hello-project/summary.expected @@ -1,9 +1,9 @@ | Extraction errors | 0 | -| Extraction warnings | 1 | +| Extraction warnings | 0 | | Files extracted - total | 5 | -| Files extracted - with errors | 1 | -| Files extracted - without errors | 4 | -| Files extracted - without errors % | 80 | +| Files extracted - with errors | 0 | +| Files extracted - without errors | 5 | +| Files extracted - without errors % | 100 | | Inconsistencies - AST | 0 | | Inconsistencies - CFG | 0 | | Inconsistencies - Path resolution | 0 | diff --git a/rust/ql/test/extractor-tests/macro-expansion/CONSISTENCY/ExtractionConsistency.expected b/rust/ql/test/extractor-tests/macro-expansion/CONSISTENCY/ExtractionConsistency.expected index 2d13c81bdab8..f356396d4ed1 100644 --- a/rust/ql/test/extractor-tests/macro-expansion/CONSISTENCY/ExtractionConsistency.expected +++ b/rust/ql/test/extractor-tests/macro-expansion/CONSISTENCY/ExtractionConsistency.expected @@ -1,3 +1,2 @@ extractionWarning -| included/included.rs:1:1:1:1 | semantic analyzer unavailable (not loaded as its own module, probably included by `!include`) | | macro_expansion.rs:56:9:56:31 | macro expansion failed: could not resolve macro 'concat' | diff --git a/rust/ql/test/extractor-tests/macro-expansion/test.expected b/rust/ql/test/extractor-tests/macro-expansion/test.expected index 5001751e5c3b..a60b8d77a4c3 100644 --- a/rust/ql/test/extractor-tests/macro-expansion/test.expected +++ b/rust/ql/test/extractor-tests/macro-expansion/test.expected @@ -51,5 +51,4 @@ unexpanded_macro_calls | macro_expansion.rs:56:9:56:31 | concat!... | | macro_expansion.rs:63:9:63:32 | include_str!... | warnings -| included/included.rs:1:1:1:1 | semantic analyzer unavailable (not loaded as its own module, probably included by `!include`) | | macro_expansion.rs:56:9:56:31 | macro expansion failed: could not resolve macro 'concat' | diff --git a/rust/ql/test/library-tests/type-inference/CONSISTENCY/ExtractionConsistency.expected b/rust/ql/test/library-tests/type-inference/CONSISTENCY/ExtractionConsistency.expected deleted file mode 100644 index 0b4e0c12d0c8..000000000000 --- a/rust/ql/test/library-tests/type-inference/CONSISTENCY/ExtractionConsistency.expected +++ /dev/null @@ -1,2 +0,0 @@ -extractionWarning -| loop/main.rs:1:1:1:1 | semantic analyzer unavailable (not included as a module) | diff --git a/rust/ql/test/query-tests/unusedentities/CONSISTENCY/ExtractionConsistency.expected b/rust/ql/test/query-tests/unusedentities/CONSISTENCY/ExtractionConsistency.expected deleted file mode 100644 index f3834c238893..000000000000 --- a/rust/ql/test/query-tests/unusedentities/CONSISTENCY/ExtractionConsistency.expected +++ /dev/null @@ -1,2 +0,0 @@ -extractionWarning -| undefined_macros/main.rs:1:1:1:1 | semantic analyzer unavailable (not included as a module) | From 42a40c14ace093621ec5e752350e06d8c57dcf7a Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Tue, 26 Aug 2025 13:58:47 +0200 Subject: [PATCH 3/3] Rust: reword macro expansion error --- rust/extractor/src/translate/base.rs | 2 +- .../macro-expansion/CONSISTENCY/ExtractionConsistency.expected | 2 +- rust/ql/test/extractor-tests/macro-expansion/test.expected | 2 +- .../diagnostics/CONSISTENCY/ExtractionConsistency.expected | 2 +- .../ql/test/query-tests/diagnostics/ExtractionWarnings.expected | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rust/extractor/src/translate/base.rs b/rust/extractor/src/translate/base.rs index 7433bf2138dc..347fdbdb715c 100644 --- a/rust/extractor/src/translate/base.rs +++ b/rust/extractor/src/translate/base.rs @@ -514,7 +514,7 @@ impl<'a> Translator<'a> { mcall, &SyntaxError::new( format!( - "macro expansion failed: could not resolve macro '{}'", + "macro expansion failed for '{}'", mcall.path().map(|p| p.to_string()).unwrap_or_default() ), range.unwrap_or_else(|| TextRange::empty(TextSize::from(0))), diff --git a/rust/ql/test/extractor-tests/macro-expansion/CONSISTENCY/ExtractionConsistency.expected b/rust/ql/test/extractor-tests/macro-expansion/CONSISTENCY/ExtractionConsistency.expected index f356396d4ed1..5c472b07a14f 100644 --- a/rust/ql/test/extractor-tests/macro-expansion/CONSISTENCY/ExtractionConsistency.expected +++ b/rust/ql/test/extractor-tests/macro-expansion/CONSISTENCY/ExtractionConsistency.expected @@ -1,2 +1,2 @@ extractionWarning -| macro_expansion.rs:56:9:56:31 | macro expansion failed: could not resolve macro 'concat' | +| macro_expansion.rs:56:9:56:31 | macro expansion failed for 'concat' | diff --git a/rust/ql/test/extractor-tests/macro-expansion/test.expected b/rust/ql/test/extractor-tests/macro-expansion/test.expected index a60b8d77a4c3..deb522796c9e 100644 --- a/rust/ql/test/extractor-tests/macro-expansion/test.expected +++ b/rust/ql/test/extractor-tests/macro-expansion/test.expected @@ -51,4 +51,4 @@ unexpanded_macro_calls | macro_expansion.rs:56:9:56:31 | concat!... | | macro_expansion.rs:63:9:63:32 | include_str!... | warnings -| macro_expansion.rs:56:9:56:31 | macro expansion failed: could not resolve macro 'concat' | +| macro_expansion.rs:56:9:56:31 | macro expansion failed for 'concat' | diff --git a/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected b/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected index f1c469a407da..82c29ac7f2b0 100644 --- a/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected +++ b/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected @@ -5,4 +5,4 @@ extractionWarning | does_not_compile.rs:2:21:2:20 | expected SEMICOLON | | does_not_compile.rs:2:26:2:25 | expected SEMICOLON | | error.rs:2:5:2:17 | An error! | -| my_macro.rs:17:9:17:27 | macro expansion failed: could not resolve macro 'myUndefinedMacro' | +| my_macro.rs:17:9:17:27 | macro expansion failed for 'myUndefinedMacro' | diff --git a/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.expected b/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.expected index 7f14093f20e5..22a2f381a9d1 100644 --- a/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.expected +++ b/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.expected @@ -4,4 +4,4 @@ | does_not_compile.rs:2:21:2:20 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 | | does_not_compile.rs:2:26:2:25 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 | | error.rs:2:5:2:17 | An error! | Extraction warning in error.rs with message An error! | 1 | -| my_macro.rs:17:9:17:27 | macro expansion failed: could not resolve macro 'myUndefinedMacro' | Extraction warning in my_macro.rs with message macro expansion failed: could not resolve macro 'myUndefinedMacro' | 1 | +| my_macro.rs:17:9:17:27 | macro expansion failed for 'myUndefinedMacro' | Extraction warning in my_macro.rs with message macro expansion failed for 'myUndefinedMacro' | 1 |