@@ -11,9 +11,9 @@ use hir::{
11
11
db:: { AstDatabase , DefDatabase , HirDatabase } ,
12
12
AssocItem , Crate , Function , HasSource , HirDisplay , ModuleDef ,
13
13
} ;
14
- use hir_def:: FunctionId ;
14
+ use hir_def:: { body :: BodySourceMap , expr :: ExprId , FunctionId } ;
15
15
use hir_ty:: { TyExt , TypeWalk } ;
16
- use ide:: { AnalysisHost , RootDatabase } ;
16
+ use ide:: { Analysis , AnalysisHost , LineCol , RootDatabase } ;
17
17
use ide_db:: base_db:: {
18
18
salsa:: { self , ParallelDatabase } ,
19
19
SourceDatabaseExt ,
@@ -25,7 +25,7 @@ use rayon::prelude::*;
25
25
use rustc_hash:: FxHashSet ;
26
26
use stdx:: format_to;
27
27
use syntax:: AstNode ;
28
- use vfs:: Vfs ;
28
+ use vfs:: { Vfs , VfsPath } ;
29
29
30
30
use crate :: cli:: {
31
31
load_cargo:: { load_workspace_at, LoadCargoConfig } ,
@@ -191,6 +191,7 @@ impl AnalysisStatsCmd {
191
191
let mut num_exprs_unknown = 0 ;
192
192
let mut num_exprs_partially_unknown = 0 ;
193
193
let mut num_type_mismatches = 0 ;
194
+ let analysis = host. analysis ( ) ;
194
195
for f in funcs. iter ( ) . copied ( ) {
195
196
let name = f. name ( db) ;
196
197
let full_name = f
@@ -220,7 +221,7 @@ impl AnalysisStatsCmd {
220
221
}
221
222
bar. set_message ( & msg) ;
222
223
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 ( ) ) ;
224
225
let inference_result = db. infer ( f_id. into ( ) ) ;
225
226
let ( previous_exprs, previous_unknown, previous_partially_unknown) =
226
227
( num_exprs, num_exprs_unknown, num_exprs_partially_unknown) ;
@@ -229,6 +230,22 @@ impl AnalysisStatsCmd {
229
230
num_exprs += 1 ;
230
231
if ty. is_unknown ( ) {
231
232
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
+ }
232
249
} else {
233
250
let mut is_partially_unknown = false ;
234
251
ty. walk ( & mut |ty| {
@@ -242,20 +259,9 @@ impl AnalysisStatsCmd {
242
259
}
243
260
if self . only . is_some ( ) && verbosity. is_spammy ( ) {
244
261
// 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
+ {
259
265
bar. println ( format ! (
260
266
"{}:{}-{}:{}: {}" ,
261
267
start. line + 1 ,
@@ -271,22 +277,9 @@ impl AnalysisStatsCmd {
271
277
if let Some ( mismatch) = inference_result. type_mismatch_for_expr ( expr_id) {
272
278
num_type_mismatches += 1 ;
273
279
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
+ {
290
283
bar. println ( format ! (
291
284
"{} {}:{}-{}:{}: Expected {}, got {}" ,
292
285
path,
@@ -319,6 +312,7 @@ impl AnalysisStatsCmd {
319
312
}
320
313
bar. inc ( 1 ) ;
321
314
}
315
+
322
316
bar. finish_and_clear ( ) ;
323
317
eprintln ! (
324
318
" exprs: {}, ??ty: {} ({}%), ?ty: {} ({}%), !ty: {}" ,
@@ -340,6 +334,31 @@ impl AnalysisStatsCmd {
340
334
}
341
335
}
342
336
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
+
343
362
fn shuffle < T > ( rng : & mut Rand32 , slice : & mut [ T ] ) {
344
363
for i in 0 ..slice. len ( ) {
345
364
randomize_first ( rng, & mut slice[ i..] ) ;
0 commit comments