]> git.lizzy.rs Git - rust.git/blob - crates/rust-analyzer/src/cli/diagnostics.rs
Add a way to resolve certain assists
[rust.git] / crates / rust-analyzer / src / cli / diagnostics.rs
1 //! Analyze all modules in a project for diagnostics. Exits with a non-zero status
2 //! code if any errors are found.
3
4 use std::path::Path;
5
6 use anyhow::anyhow;
7 use rustc_hash::FxHashSet;
8
9 use hir::{db::HirDatabase, Crate, Module};
10 use ide::{AssistResolveStrategy, DiagnosticsConfig, Severity};
11 use ide_db::base_db::SourceDatabaseExt;
12
13 use crate::cli::{
14     load_cargo::{load_workspace_at, LoadCargoConfig},
15     Result,
16 };
17
18 fn all_modules(db: &dyn HirDatabase) -> Vec<Module> {
19     let mut worklist: Vec<_> =
20         Crate::all(db).into_iter().map(|krate| krate.root_module(db)).collect();
21     let mut modules = Vec::new();
22
23     while let Some(module) = worklist.pop() {
24         modules.push(module);
25         worklist.extend(module.children(db));
26     }
27
28     modules
29 }
30
31 pub fn diagnostics(
32     path: &Path,
33     load_out_dirs_from_check: bool,
34     with_proc_macro: bool,
35 ) -> Result<()> {
36     let cargo_config = Default::default();
37     let load_cargo_config =
38         LoadCargoConfig { load_out_dirs_from_check, with_proc_macro, wrap_rustc: false };
39     let (host, _vfs, _proc_macro) =
40         load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?;
41     let db = host.raw_database();
42     let analysis = host.analysis();
43
44     let mut found_error = false;
45     let mut visited_files = FxHashSet::default();
46
47     let work = all_modules(db).into_iter().filter(|module| {
48         let file_id = module.definition_source(db).file_id.original_file(db);
49         let source_root = db.file_source_root(file_id);
50         let source_root = db.source_root(source_root);
51         !source_root.is_library
52     });
53
54     for module in work {
55         let file_id = module.definition_source(db).file_id.original_file(db);
56         if !visited_files.contains(&file_id) {
57             let crate_name =
58                 module.krate().display_name(db).as_deref().unwrap_or("unknown").to_string();
59             println!("processing crate: {}, module: {}", crate_name, _vfs.file_path(file_id));
60             for diagnostic in analysis
61                 .diagnostics(&DiagnosticsConfig::default(), AssistResolveStrategy::None, file_id)
62                 .unwrap()
63             {
64                 if matches!(diagnostic.severity, Severity::Error) {
65                     found_error = true;
66                 }
67
68                 println!("{:?}", diagnostic);
69             }
70
71             visited_files.insert(file_id);
72         }
73     }
74
75     println!();
76     println!("diagnostic scan complete");
77
78     if found_error {
79         println!();
80         Err(anyhow!("diagnostic error detected"))
81     } else {
82         Ok(())
83     }
84 }