diff options
-rw-r--r-- | crates/rust-analyzer/src/bin/args.rs | 7 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/main.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/diagnostics.rs | 90 |
3 files changed, 51 insertions, 50 deletions
diff --git a/crates/rust-analyzer/src/bin/args.rs b/crates/rust-analyzer/src/bin/args.rs index 25367df45..f5981588a 100644 --- a/crates/rust-analyzer/src/bin/args.rs +++ b/crates/rust-analyzer/src/bin/args.rs | |||
@@ -38,6 +38,9 @@ pub(crate) enum Command { | |||
38 | Diagnostics { | 38 | Diagnostics { |
39 | path: PathBuf, | 39 | path: PathBuf, |
40 | load_output_dirs: bool, | 40 | load_output_dirs: bool, |
41 | /// Include files which are not modules. In rust-analyzer | ||
42 | /// this would include the parser test files. | ||
43 | all: bool, | ||
41 | }, | 44 | }, |
42 | RunServer, | 45 | RunServer, |
43 | Version, | 46 | Version, |
@@ -225,6 +228,7 @@ USAGE: | |||
225 | FLAGS: | 228 | FLAGS: |
226 | -h, --help Prints help information | 229 | -h, --help Prints help information |
227 | --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis | 230 | --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis |
231 | --all Include all files rather than only modules | ||
228 | 232 | ||
229 | ARGS: | 233 | ARGS: |
230 | <PATH>" | 234 | <PATH>" |
@@ -233,6 +237,7 @@ ARGS: | |||
233 | } | 237 | } |
234 | 238 | ||
235 | let load_output_dirs = matches.contains("--load-output-dirs"); | 239 | let load_output_dirs = matches.contains("--load-output-dirs"); |
240 | let all = matches.contains("--all"); | ||
236 | let path = { | 241 | let path = { |
237 | let mut trailing = matches.free()?; | 242 | let mut trailing = matches.free()?; |
238 | if trailing.len() != 1 { | 243 | if trailing.len() != 1 { |
@@ -241,7 +246,7 @@ ARGS: | |||
241 | trailing.pop().unwrap().into() | 246 | trailing.pop().unwrap().into() |
242 | }; | 247 | }; |
243 | 248 | ||
244 | Command::Diagnostics { path, load_output_dirs } | 249 | Command::Diagnostics { path, load_output_dirs, all } |
245 | } | 250 | } |
246 | _ => { | 251 | _ => { |
247 | eprintln!( | 252 | eprintln!( |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 4edd617ee..7cfc44f01 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -39,8 +39,8 @@ fn main() -> Result<()> { | |||
39 | cli::analysis_bench(args.verbosity, path.as_ref(), what, load_output_dirs)? | 39 | cli::analysis_bench(args.verbosity, path.as_ref(), what, load_output_dirs)? |
40 | } | 40 | } |
41 | 41 | ||
42 | args::Command::Diagnostics { path, load_output_dirs } => { | 42 | args::Command::Diagnostics { path, load_output_dirs, all } => { |
43 | cli::diagnostics(path.as_ref(), load_output_dirs)? | 43 | cli::diagnostics(path.as_ref(), load_output_dirs, all)? |
44 | } | 44 | } |
45 | 45 | ||
46 | args::Command::RunServer => run_server()?, | 46 | args::Command::RunServer => run_server()?, |
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs index f5aab89a2..2d92c1f78 100644 --- a/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/crates/rust-analyzer/src/cli/diagnostics.rs | |||
@@ -1,36 +1,61 @@ | |||
1 | //! Analyze all files in project for diagnostics. Exits with a non-zero status | 1 | //! Analyze all modules in a project for diagnostics. Exits with a non-zero status |
2 | //! code if any errors are found. | 2 | //! code if any errors are found. |
3 | 3 | ||
4 | use anyhow::anyhow; | 4 | use anyhow::anyhow; |
5 | use ra_db::{SourceDatabaseExt, SourceRootId}; | 5 | use ra_db::{SourceDatabase, SourceDatabaseExt}; |
6 | use ra_ide::{Analysis, Severity}; | 6 | use ra_ide::Severity; |
7 | use std::{collections::HashSet, path::Path}; | 7 | use std::{collections::HashSet, path::Path}; |
8 | 8 | ||
9 | use crate::cli::{load_cargo::load_cargo, Result}; | 9 | use crate::cli::{load_cargo::load_cargo, Result}; |
10 | use hir::{db::HirDatabase, Crate, Module}; | 10 | use hir::Semantics; |
11 | 11 | ||
12 | pub fn diagnostics(path: &Path, load_output_dirs: bool) -> Result<()> { | 12 | pub fn diagnostics(path: &Path, load_output_dirs: bool, all: bool) -> Result<()> { |
13 | let (host, roots) = load_cargo(path, load_output_dirs)?; | 13 | let (host, roots) = load_cargo(path, load_output_dirs)?; |
14 | let db = host.raw_database(); | 14 | let db = host.raw_database(); |
15 | let analysis = host.analysis(); | 15 | let analysis = host.analysis(); |
16 | let semantics = Semantics::new(db); | ||
16 | let members = roots | 17 | let members = roots |
17 | .into_iter() | 18 | .into_iter() |
18 | .filter_map( | 19 | .filter_map(|(source_root_id, project_root)| { |
19 | |(source_root_id, project_root)| { | 20 | // filter out dependencies |
20 | if project_root.is_member() { | 21 | if project_root.is_member() { |
21 | Some(source_root_id) | 22 | Some(source_root_id) |
22 | } else { | 23 | } else { |
23 | None | 24 | None |
24 | } | 25 | } |
25 | }, | 26 | }) |
26 | ) | ||
27 | .collect::<HashSet<_>>(); | 27 | .collect::<HashSet<_>>(); |
28 | 28 | ||
29 | let mut found_error = false; | 29 | let mut found_error = false; |
30 | let mut visited_modules = HashSet::new(); | 30 | let mut visited_files = HashSet::new(); |
31 | for krate in Crate::all(db) { | 31 | let crate_graph = db.crate_graph(); |
32 | let module = krate.root_module(db).expect("crate without root module"); | 32 | for crate_id in crate_graph.iter() { |
33 | check_module(module, db, &mut visited_modules, &members, &analysis, &mut found_error); | 33 | let krate = &crate_graph[crate_id]; |
34 | if let Some(crate_name) = &krate.display_name { | ||
35 | println!("processing crate: {}", crate_name); | ||
36 | } else { | ||
37 | println!("processing crate: unknown"); | ||
38 | } | ||
39 | for file_id in db.source_root(db.file_source_root(krate.root_file_id)).walk() { | ||
40 | // Filter out files which are not actually modules (unless `--all` flag is | ||
41 | // passed). In the rust-analyzer repository this filters out the parser test files. | ||
42 | if semantics.to_module_def(file_id).is_some() || all { | ||
43 | if !visited_files.contains(&file_id) { | ||
44 | if members.contains(&db.file_source_root(file_id)) { | ||
45 | println!("processing module: {}", db.file_relative_path(file_id)); | ||
46 | for diagnostic in analysis.diagnostics(file_id).unwrap() { | ||
47 | if matches!(diagnostic.severity, Severity::Error) { | ||
48 | found_error = true; | ||
49 | } | ||
50 | |||
51 | println!("{:?}", diagnostic); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | visited_files.insert(file_id); | ||
56 | } | ||
57 | } | ||
58 | } | ||
34 | } | 59 | } |
35 | 60 | ||
36 | println!(); | 61 | println!(); |
@@ -43,32 +68,3 @@ pub fn diagnostics(path: &Path, load_output_dirs: bool) -> Result<()> { | |||
43 | Ok(()) | 68 | Ok(()) |
44 | } | 69 | } |
45 | } | 70 | } |
46 | |||
47 | fn check_module( | ||
48 | module: Module, | ||
49 | db: &(impl HirDatabase + SourceDatabaseExt), | ||
50 | visited_modules: &mut HashSet<Module>, | ||
51 | members: &HashSet<SourceRootId>, | ||
52 | analysis: &Analysis, | ||
53 | found_error: &mut bool, | ||
54 | ) { | ||
55 | let file_id = module.definition_source(db).file_id.original_file(db); | ||
56 | if !visited_modules.contains(&module) { | ||
57 | if members.contains(&db.file_source_root(file_id)) { | ||
58 | println!("processing: {}", db.file_relative_path(file_id)); | ||
59 | for diagnostic in analysis.diagnostics(file_id).unwrap() { | ||
60 | if matches!(diagnostic.severity, Severity::Error) { | ||
61 | *found_error = true; | ||
62 | } | ||
63 | |||
64 | println!("{:?}", diagnostic); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | visited_modules.insert(module); | ||
69 | |||
70 | for child_module in module.children(db) { | ||
71 | check_module(child_module, db, visited_modules, members, analysis, found_error); | ||
72 | } | ||
73 | } | ||
74 | } | ||