Skip to content

Commit 3cb3f1d

Browse files
bors[bot]lnicola
andauthored
9025: internal: Display unknown types in `analysis-stats` r=flodiebold a=lnicola Co-authored-by: Laurențiu Nicola <lnicola@dend.ro>
2 parents c7ae418 + aabbc84 commit 3cb3f1d

File tree

1 file changed

+53
-34
lines changed

1 file changed

+53
-34
lines changed

crates/rust-analyzer/src/cli/analysis_stats.rs

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ use hir::{
1111
db::{AstDatabase, DefDatabase, HirDatabase},
1212
AssocItem, Crate, Function, HasSource, HirDisplay, ModuleDef,
1313
};
14-
use hir_def::FunctionId;
14+
use hir_def::{body::BodySourceMap, expr::ExprId, FunctionId};
1515
use hir_ty::{TyExt, TypeWalk};
16-
use ide::{AnalysisHost, RootDatabase};
16+
use ide::{Analysis, AnalysisHost, LineCol, RootDatabase};
1717
use ide_db::base_db::{
1818
salsa::{self, ParallelDatabase},
1919
SourceDatabaseExt,
@@ -25,7 +25,7 @@ use rayon::prelude::*;
2525
use rustc_hash::FxHashSet;
2626
use stdx::format_to;
2727
use syntax::AstNode;
28-
use vfs::Vfs;
28+
use vfs::{Vfs, VfsPath};
2929

3030
use crate::cli::{
3131
load_cargo::{load_workspace_at, LoadCargoConfig},
@@ -191,6 +191,7 @@ impl AnalysisStatsCmd {
191191
let mut num_exprs_unknown = 0;
192192
let mut num_exprs_partially_unknown = 0;
193193
let mut num_type_mismatches = 0;
194+
let analysis = host.analysis();
194195
for f in funcs.iter().copied() {
195196
let name = f.name(db);
196197
let full_name = f
@@ -220,7 +221,7 @@ impl AnalysisStatsCmd {
220221
}
221222
bar.set_message(&msg);
222223
let f_id = FunctionId::from(f);
223-
let body = db.body(f_id.into());
224+
let (body, sm) = db.body_with_source_map(f_id.into());
224225
let inference_result = db.infer(f_id.into());
225226
let (previous_exprs, previous_unknown, previous_partially_unknown) =
226227
(num_exprs, num_exprs_unknown, num_exprs_partially_unknown);
@@ -229,6 +230,22 @@ impl AnalysisStatsCmd {
229230
num_exprs += 1;
230231
if ty.is_unknown() {
231232
num_exprs_unknown += 1;
233+
if verbosity.is_spammy() {
234+
if let Some((path, start, end)) =
235+
expr_syntax_range(db, &analysis, vfs, &sm, expr_id)
236+
{
237+
bar.println(format!(
238+
"{} {}:{}-{}:{}: Unknown type",
239+
path,
240+
start.line + 1,
241+
start.col,
242+
end.line + 1,
243+
end.col,
244+
));
245+
} else {
246+
bar.println(format!("{}: Unknown type", name,));
247+
}
248+
}
232249
} else {
233250
let mut is_partially_unknown = false;
234251
ty.walk(&mut |ty| {
@@ -242,20 +259,9 @@ impl AnalysisStatsCmd {
242259
}
243260
if self.only.is_some() && verbosity.is_spammy() {
244261
// in super-verbose mode for just one function, we print every single expression
245-
let (_, sm) = db.body_with_source_map(f_id.into());
246-
let src = sm.expr_syntax(expr_id);
247-
if let Ok(src) = src {
248-
let node = {
249-
let root = db.parse_or_expand(src.file_id).unwrap();
250-
src.value.to_node(&root)
251-
};
252-
let original_file = src.file_id.original_file(db);
253-
let line_index = host.analysis().file_line_index(original_file).unwrap();
254-
let text_range = node.syntax().text_range();
255-
let (start, end) = (
256-
line_index.line_col(text_range.start()),
257-
line_index.line_col(text_range.end()),
258-
);
262+
if let Some((_, start, end)) =
263+
expr_syntax_range(db, &analysis, vfs, &sm, expr_id)
264+
{
259265
bar.println(format!(
260266
"{}:{}-{}:{}: {}",
261267
start.line + 1,
@@ -271,22 +277,9 @@ impl AnalysisStatsCmd {
271277
if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
272278
num_type_mismatches += 1;
273279
if verbosity.is_verbose() {
274-
let (_, sm) = db.body_with_source_map(f_id.into());
275-
let src = sm.expr_syntax(expr_id);
276-
if let Ok(src) = src {
277-
// FIXME: it might be nice to have a function (on Analysis?) that goes from Source<T> -> (LineCol, LineCol) directly
278-
// But also, we should just turn the type mismatches into diagnostics and provide these
279-
let root = db.parse_or_expand(src.file_id).unwrap();
280-
let node = src.map(|e| e.to_node(&root).syntax().clone());
281-
let original_range = node.as_ref().original_file_range(db);
282-
let path = vfs.file_path(original_range.file_id);
283-
let line_index =
284-
host.analysis().file_line_index(original_range.file_id).unwrap();
285-
let text_range = original_range.range;
286-
let (start, end) = (
287-
line_index.line_col(text_range.start()),
288-
line_index.line_col(text_range.end()),
289-
);
280+
if let Some((path, start, end)) =
281+
expr_syntax_range(db, &analysis, vfs, &sm, expr_id)
282+
{
290283
bar.println(format!(
291284
"{} {}:{}-{}:{}: Expected {}, got {}",
292285
path,
@@ -319,6 +312,7 @@ impl AnalysisStatsCmd {
319312
}
320313
bar.inc(1);
321314
}
315+
322316
bar.finish_and_clear();
323317
eprintln!(
324318
" exprs: {}, ??ty: {} ({}%), ?ty: {} ({}%), !ty: {}",
@@ -340,6 +334,31 @@ impl AnalysisStatsCmd {
340334
}
341335
}
342336

337+
fn expr_syntax_range(
338+
db: &RootDatabase,
339+
analysis: &Analysis,
340+
vfs: &Vfs,
341+
sm: &BodySourceMap,
342+
expr_id: ExprId,
343+
) -> Option<(VfsPath, LineCol, LineCol)> {
344+
let src = sm.expr_syntax(expr_id);
345+
if let Ok(src) = src {
346+
// FIXME: it might be nice to have a function (on Analysis?) that goes from Source<T> -> (LineCol, LineCol) directly
347+
// But also, we should just turn the type mismatches into diagnostics and provide these
348+
let root = db.parse_or_expand(src.file_id).unwrap();
349+
let node = src.map(|e| e.to_node(&root).syntax().clone());
350+
let original_range = node.as_ref().original_file_range(db);
351+
let path = vfs.file_path(original_range.file_id);
352+
let line_index = analysis.file_line_index(original_range.file_id).unwrap();
353+
let text_range = original_range.range;
354+
let (start, end) =
355+
(line_index.line_col(text_range.start()), line_index.line_col(text_range.end()));
356+
Some((path, start, end))
357+
} else {
358+
None
359+
}
360+
}
361+
343362
fn shuffle<T>(rng: &mut Rand32, slice: &mut [T]) {
344363
for i in 0..slice.len() {
345364
randomize_first(rng, &mut slice[i..]);

0 commit comments

Comments
 (0)