aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_batch/src/lib.rs9
-rw-r--r--crates/ra_cli/Cargo.toml6
-rw-r--r--crates/ra_cli/src/analysis_stats.rs100
-rw-r--r--crates/ra_cli/src/main.rs11
-rw-r--r--crates/ra_db/src/input.rs1
-rw-r--r--crates/ra_hir/src/code_model_api.rs34
-rw-r--r--crates/ra_hir/src/expr.rs8
-rw-r--r--crates/ra_hir/src/ty.rs35
8 files changed, 200 insertions, 4 deletions
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index ea91d88b7..014663546 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -60,7 +60,11 @@ impl BatchDatabase {
60 match change { 60 match change {
61 VfsChange::AddRoot { root, files } => { 61 VfsChange::AddRoot { root, files } => {
62 let source_root_id = vfs_root_to_id(root); 62 let source_root_id = vfs_root_to_id(root);
63 log::debug!("loaded source root {:?} with path {:?}", source_root_id, vfs.root2path(root)); 63 log::debug!(
64 "loaded source root {:?} with path {:?}",
65 source_root_id,
66 vfs.root2path(root)
67 );
64 let mut file_map = FxHashMap::default(); 68 let mut file_map = FxHashMap::default();
65 for (vfs_file, path, text) in files { 69 for (vfs_file, path, text) in files {
66 let file_id = vfs_file_to_id(vfs_file); 70 let file_id = vfs_file_to_id(vfs_file);
@@ -111,7 +115,8 @@ impl BatchDatabase {
111 let crate_graph = ws.to_crate_graph(&mut load); 115 let crate_graph = ws.to_crate_graph(&mut load);
112 log::debug!("crate graph: {:?}", crate_graph); 116 log::debug!("crate graph: {:?}", crate_graph);
113 117
114 let local_roots = roots.into_iter() 118 let local_roots = roots
119 .into_iter()
115 .filter(|r| vfs.root2path(*r).starts_with(&root)) 120 .filter(|r| vfs.root2path(*r).starts_with(&root))
116 .map(vfs_root_to_id) 121 .map(vfs_root_to_id)
117 .collect(); 122 .collect();
diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml
index eb1722d5e..641ac5cbd 100644
--- a/crates/ra_cli/Cargo.toml
+++ b/crates/ra_cli/Cargo.toml
@@ -9,6 +9,12 @@ publish = false
9clap = "2.32.0" 9clap = "2.32.0"
10failure = "0.1.4" 10failure = "0.1.4"
11join_to_string = "0.1.1" 11join_to_string = "0.1.1"
12flexi_logger = "0.10.0"
13indicatif = "0.11.0"
14
12ra_syntax = { path = "../ra_syntax" } 15ra_syntax = { path = "../ra_syntax" }
13ra_ide_api_light = { path = "../ra_ide_api_light" } 16ra_ide_api_light = { path = "../ra_ide_api_light" }
14tools = { path = "../tools" } 17tools = { path = "../tools" }
18ra_batch = { path = "../ra_batch" }
19ra_hir = { path = "../ra_hir" }
20ra_db = { path = "../ra_db" }
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}
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index a4debeb48..72e6ae4d5 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -1,3 +1,5 @@
1mod analysis_stats;
2
1use std::{fs, io::Read, path::Path, time::Instant}; 3use std::{fs, io::Read, path::Path, time::Instant};
2 4
3use clap::{App, Arg, SubCommand}; 5use clap::{App, Arg, SubCommand};
@@ -5,10 +7,12 @@ use join_to_string::join;
5use ra_ide_api_light::{extend_selection, file_structure, syntax_tree}; 7use ra_ide_api_light::{extend_selection, file_structure, syntax_tree};
6use ra_syntax::{SourceFile, TextRange, TreeArc, AstNode}; 8use ra_syntax::{SourceFile, TextRange, TreeArc, AstNode};
7use tools::collect_tests; 9use tools::collect_tests;
10use flexi_logger::Logger;
8 11
9type Result<T> = ::std::result::Result<T, failure::Error>; 12type Result<T> = ::std::result::Result<T, failure::Error>;
10 13
11fn main() -> Result<()> { 14fn main() -> Result<()> {
15 Logger::with_env().start()?;
12 let matches = App::new("ra-cli") 16 let matches = App::new("ra-cli")
13 .setting(clap::AppSettings::SubcommandRequiredElseHelp) 17 .setting(clap::AppSettings::SubcommandRequiredElseHelp)
14 .subcommand( 18 .subcommand(
@@ -23,6 +27,9 @@ fn main() -> Result<()> {
23 .arg(Arg::with_name("start")) 27 .arg(Arg::with_name("start"))
24 .arg(Arg::with_name("end")), 28 .arg(Arg::with_name("end")),
25 ) 29 )
30 .subcommand(
31 SubCommand::with_name("analysis-stats").arg(Arg::with_name("verbose").short("v")),
32 )
26 .get_matches(); 33 .get_matches();
27 match matches.subcommand() { 34 match matches.subcommand() {
28 ("parse", Some(matches)) => { 35 ("parse", Some(matches)) => {
@@ -56,6 +63,10 @@ fn main() -> Result<()> {
56 let sels = selections(&file, start, end); 63 let sels = selections(&file, start, end);
57 println!("{}", sels) 64 println!("{}", sels)
58 } 65 }
66 ("analysis-stats", Some(matches)) => {
67 let verbose = matches.is_present("verbose");
68 analysis_stats::run(verbose)?;
69 }
59 _ => unreachable!(), 70 _ => unreachable!(),
60 } 71 }
61 Ok(()) 72 Ok(())
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index 405634fe0..8decc65c5 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -112,6 +112,7 @@ impl CrateGraph {
112 self.arena[&crate_id].file_id 112 self.arena[&crate_id].file_id
113 } 113 }
114 114
115 // TODO: this only finds one crate with the given root; we could have multiple
115 pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> { 116 pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
116 let (&crate_id, _) = self.arena.iter().find(|(_crate_id, data)| data.file_id == file_id)?; 117 let (&crate_id, _) = self.arena.iter().find(|(_crate_id, data)| data.file_id == file_id)?;
117 Some(crate_id) 118 Some(crate_id)
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index cafc5279d..19f103855 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -1,7 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use relative_path::RelativePathBuf; 3use relative_path::RelativePathBuf;
4use ra_db::{CrateId, FileId}; 4use ra_db::{CrateId, FileId, SourceRootId};
5use ra_syntax::{ast::self, TreeArc, SyntaxNode}; 5use ra_syntax::{ast::self, TreeArc, SyntaxNode};
6 6
7use crate::{ 7use crate::{
@@ -16,7 +16,7 @@ use crate::{
16 docs::{Documentation, Docs, docs_from_ast}, 16 docs::{Documentation, Docs, docs_from_ast},
17 module_tree::ModuleId, 17 module_tree::ModuleId,
18 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, 18 ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId},
19 impl_block::ImplId, 19 impl_block::{ImplId, ImplBlock},
20 resolve::Resolver, 20 resolve::Resolver,
21}; 21};
22 22
@@ -44,6 +44,15 @@ impl Crate {
44 pub fn root_module(&self, db: &impl PersistentHirDatabase) -> Option<Module> { 44 pub fn root_module(&self, db: &impl PersistentHirDatabase) -> Option<Module> {
45 self.root_module_impl(db) 45 self.root_module_impl(db)
46 } 46 }
47
48 // TODO: should this be in source_binder?
49 pub fn source_root_crates(
50 db: &impl PersistentHirDatabase,
51 source_root: SourceRootId,
52 ) -> Vec<Crate> {
53 let crate_ids = db.source_root_crates(source_root);
54 crate_ids.iter().map(|&crate_id| Crate { crate_id }).collect()
55 }
47} 56}
48 57
49#[derive(Debug)] 58#[derive(Debug)]
@@ -168,6 +177,27 @@ impl Module {
168 let item_map = db.item_map(self.krate); 177 let item_map = db.item_map(self.krate);
169 Resolver::default().push_module_scope(item_map, *self) 178 Resolver::default().push_module_scope(item_map, *self)
170 } 179 }
180
181 pub fn declarations(self, db: &impl HirDatabase) -> Vec<ModuleDef> {
182 let (lowered_module, _) = db.lower_module(self);
183 lowered_module
184 .declarations
185 .values()
186 .cloned()
187 .flat_map(|per_ns| {
188 per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
189 })
190 .collect()
191 }
192
193 pub fn impl_blocks(self, db: &impl HirDatabase) -> Vec<ImplBlock> {
194 let module_impl_blocks = db.impls_in_module(self);
195 module_impl_blocks
196 .impls
197 .iter()
198 .map(|(impl_id, _)| ImplBlock::from_id(module_impl_blocks.clone(), impl_id))
199 .collect()
200 }
171} 201}
172 202
173impl Docs for Module { 203impl Docs for Module {
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index b30e11abb..4e73590d0 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -70,6 +70,14 @@ impl Body {
70 self.owner 70 self.owner
71 } 71 }
72 72
73 pub fn exprs(&self) -> impl Iterator<Item = (ExprId, &Expr)> {
74 self.exprs.iter()
75 }
76
77 pub fn pats(&self) -> impl Iterator<Item = (PatId, &Pat)> {
78 self.pats.iter()
79 }
80
73 pub fn syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { 81 pub fn syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> {
74 db.body_syntax_mapping(self.owner) 82 db.body_syntax_mapping(self.owner)
75 } 83 }
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 7203a8a10..08561573b 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -449,6 +449,41 @@ impl Ty {
449 Ty::Tuple(Arc::new([])) 449 Ty::Tuple(Arc::new([]))
450 } 450 }
451 451
452 pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
453 f(self);
454 match self {
455 Ty::Slice(t) | Ty::Array(t) => t.walk(f),
456 Ty::RawPtr(t, _) => t.walk(f),
457 Ty::Ref(t, _) => t.walk(f),
458 Ty::Tuple(ts) => {
459 for t in ts.iter() {
460 t.walk(f);
461 }
462 }
463 Ty::FnPtr(sig) => {
464 for input in &sig.input {
465 input.walk(f);
466 }
467 sig.output.walk(f);
468 }
469 Ty::FnDef { substs, sig, .. } => {
470 for input in &sig.input {
471 input.walk(f);
472 }
473 sig.output.walk(f);
474 for t in substs.0.iter() {
475 t.walk(f);
476 }
477 }
478 Ty::Adt { substs, .. } => {
479 for t in substs.0.iter() {
480 t.walk(f);
481 }
482 }
483 _ => {}
484 }
485 }
486
452 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 487 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
453 f(self); 488 f(self);
454 match self { 489 match self {