From f9701efbe706e8569a41847d76c4b914f479df32 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Tue, 14 Apr 2020 04:35:34 -0700 Subject: cli diagnostics walk files --- crates/rust-analyzer/src/bin/args.rs | 7 ++- crates/rust-analyzer/src/bin/main.rs | 4 +- crates/rust-analyzer/src/cli/diagnostics.rs | 90 ++++++++++++++--------------- 3 files changed, 51 insertions(+), 50 deletions(-) (limited to 'crates') 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 { Diagnostics { path: PathBuf, load_output_dirs: bool, + /// Include files which are not modules. In rust-analyzer + /// this would include the parser test files. + all: bool, }, RunServer, Version, @@ -225,6 +228,7 @@ USAGE: FLAGS: -h, --help Prints help information --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis + --all Include all files rather than only modules ARGS: " @@ -233,6 +237,7 @@ ARGS: } let load_output_dirs = matches.contains("--load-output-dirs"); + let all = matches.contains("--all"); let path = { let mut trailing = matches.free()?; if trailing.len() != 1 { @@ -241,7 +246,7 @@ ARGS: trailing.pop().unwrap().into() }; - Command::Diagnostics { path, load_output_dirs } + Command::Diagnostics { path, load_output_dirs, all } } _ => { 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<()> { cli::analysis_bench(args.verbosity, path.as_ref(), what, load_output_dirs)? } - args::Command::Diagnostics { path, load_output_dirs } => { - cli::diagnostics(path.as_ref(), load_output_dirs)? + args::Command::Diagnostics { path, load_output_dirs, all } => { + cli::diagnostics(path.as_ref(), load_output_dirs, all)? } 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 @@ -//! Analyze all files in project for diagnostics. Exits with a non-zero status +//! Analyze all modules in a project for diagnostics. Exits with a non-zero status //! code if any errors are found. use anyhow::anyhow; -use ra_db::{SourceDatabaseExt, SourceRootId}; -use ra_ide::{Analysis, Severity}; +use ra_db::{SourceDatabase, SourceDatabaseExt}; +use ra_ide::Severity; use std::{collections::HashSet, path::Path}; use crate::cli::{load_cargo::load_cargo, Result}; -use hir::{db::HirDatabase, Crate, Module}; +use hir::Semantics; -pub fn diagnostics(path: &Path, load_output_dirs: bool) -> Result<()> { +pub fn diagnostics(path: &Path, load_output_dirs: bool, all: bool) -> Result<()> { let (host, roots) = load_cargo(path, load_output_dirs)?; let db = host.raw_database(); let analysis = host.analysis(); + let semantics = Semantics::new(db); let members = roots .into_iter() - .filter_map( - |(source_root_id, project_root)| { - if project_root.is_member() { - Some(source_root_id) - } else { - None - } - }, - ) + .filter_map(|(source_root_id, project_root)| { + // filter out dependencies + if project_root.is_member() { + Some(source_root_id) + } else { + None + } + }) .collect::>(); let mut found_error = false; - let mut visited_modules = HashSet::new(); - for krate in Crate::all(db) { - let module = krate.root_module(db).expect("crate without root module"); - check_module(module, db, &mut visited_modules, &members, &analysis, &mut found_error); + let mut visited_files = HashSet::new(); + let crate_graph = db.crate_graph(); + for crate_id in crate_graph.iter() { + let krate = &crate_graph[crate_id]; + if let Some(crate_name) = &krate.display_name { + println!("processing crate: {}", crate_name); + } else { + println!("processing crate: unknown"); + } + for file_id in db.source_root(db.file_source_root(krate.root_file_id)).walk() { + // Filter out files which are not actually modules (unless `--all` flag is + // passed). In the rust-analyzer repository this filters out the parser test files. + if semantics.to_module_def(file_id).is_some() || all { + if !visited_files.contains(&file_id) { + if members.contains(&db.file_source_root(file_id)) { + println!("processing module: {}", db.file_relative_path(file_id)); + for diagnostic in analysis.diagnostics(file_id).unwrap() { + if matches!(diagnostic.severity, Severity::Error) { + found_error = true; + } + + println!("{:?}", diagnostic); + } + } + + visited_files.insert(file_id); + } + } + } } println!(); @@ -43,32 +68,3 @@ pub fn diagnostics(path: &Path, load_output_dirs: bool) -> Result<()> { Ok(()) } } - -fn check_module( - module: Module, - db: &(impl HirDatabase + SourceDatabaseExt), - visited_modules: &mut HashSet, - members: &HashSet, - analysis: &Analysis, - found_error: &mut bool, -) { - let file_id = module.definition_source(db).file_id.original_file(db); - if !visited_modules.contains(&module) { - if members.contains(&db.file_source_root(file_id)) { - println!("processing: {}", db.file_relative_path(file_id)); - for diagnostic in analysis.diagnostics(file_id).unwrap() { - if matches!(diagnostic.severity, Severity::Error) { - *found_error = true; - } - - println!("{:?}", diagnostic); - } - } - - visited_modules.insert(module); - - for child_module in module.children(db) { - check_module(child_module, db, visited_modules, members, analysis, found_error); - } - } -} -- cgit v1.2.3