aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_cli/src/analysis_stats.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_cli/src/analysis_stats.rs')
-rw-r--r--crates/ra_cli/src/analysis_stats.rs100
1 files changed, 100 insertions, 0 deletions
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
new file mode 100644
index 000000000..a46ac974d
--- /dev/null
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -0,0 +1,100 @@
1use std::collections::HashSet;
2
3use ra_db::SourceDatabase;
4use ra_batch::BatchDatabase;
5use ra_hir::{Crate, ModuleDef, Ty, ImplItem};
6use ra_syntax::AstNode;
7
8use crate::Result;
9
10pub fn run(verbose: bool) -> Result<()> {
11 let (db, roots) = BatchDatabase::load_cargo(".")?;
12 println!("Database loaded, {} roots", roots.len());
13 let mut num_crates = 0;
14 let mut visited_modules = HashSet::new();
15 let mut visit_queue = Vec::new();
16 for root in roots {
17 for krate in Crate::source_root_crates(&db, root) {
18 num_crates += 1;
19 let module = krate.root_module(&db).expect("crate in source root without root module");
20 visit_queue.push(module);
21 }
22 }
23 println!("Crates in this dir: {}", num_crates);
24 let mut num_decls = 0;
25 let mut funcs = Vec::new();
26 while let Some(module) = visit_queue.pop() {
27 if visited_modules.insert(module) {
28 visit_queue.extend(module.children(&db));
29
30 for decl in module.declarations(&db) {
31 num_decls += 1;
32 match decl {
33 ModuleDef::Function(f) => funcs.push(f),
34 _ => {}
35 }
36 }
37
38 for impl_block in module.impl_blocks(&db) {
39 for item in impl_block.items() {
40 num_decls += 1;
41 match item {
42 ImplItem::Method(f) => funcs.push(*f),
43 _ => {}
44 }
45 }
46 }
47 }
48 }
49 println!("Total modules found: {}", visited_modules.len());
50 println!("Total declarations: {}", num_decls);
51 println!("Total functions: {}", funcs.len());
52 let bar = indicatif::ProgressBar::new(funcs.len() as u64);
53 bar.tick();
54 let mut num_exprs = 0;
55 let mut num_exprs_unknown = 0;
56 let mut num_exprs_partially_unknown = 0;
57 for f in funcs {
58 if verbose {
59 let (file_id, source) = f.source(&db);
60 let original_file = file_id.original_file(&db);
61 let path = db.file_relative_path(original_file);
62 let syntax_range = source.syntax().range();
63 let name = f.name(&db);
64 println!("{} ({:?} {})", name, path, syntax_range);
65 }
66 let body = f.body(&db);
67 let inference_result = f.infer(&db);
68 for (expr_id, _) in body.exprs() {
69 let ty = &inference_result[expr_id];
70 num_exprs += 1;
71 if let Ty::Unknown = ty {
72 num_exprs_unknown += 1;
73 } else {
74 let mut is_partially_unknown = false;
75 ty.walk(&mut |ty| {
76 if let Ty::Unknown = ty {
77 is_partially_unknown = true;
78 }
79 });
80 if is_partially_unknown {
81 num_exprs_partially_unknown += 1;
82 }
83 }
84 }
85 bar.inc(1);
86 }
87 bar.finish_and_clear();
88 println!("Total expressions: {}", num_exprs);
89 println!(
90 "Expressions of unknown type: {} ({}%)",
91 num_exprs_unknown,
92 (num_exprs_unknown * 100 / num_exprs)
93 );
94 println!(
95 "Expressions of partially unknown type: {} ({}%)",
96 num_exprs_partially_unknown,
97 (num_exprs_partially_unknown * 100 / num_exprs)
98 );
99 Ok(())
100}