1
1
use std:: {
2
+ collections:: HashMap ,
2
3
iter:: { Enumerate , Peekable } ,
3
4
str:: Lines ,
4
5
} ;
5
6
6
7
use pgt_analyse:: { RuleCategory , RuleFilter } ;
7
- use pgt_diagnostics:: { Diagnostic , Location , MessageAndDescription } ;
8
+ use pgt_diagnostics:: { Diagnostic , MessageAndDescription } ;
8
9
use pgt_text_size:: { TextRange , TextSize } ;
9
10
10
11
pub mod line_index;
@@ -68,8 +69,6 @@ impl RuleSpecifier {
68
69
let group = self . group ( ) ;
69
70
let rule = self . rule ( ) ;
70
71
71
- tracing:: error!( "group and rule: {:#?} {:#?}" , group, rule) ;
72
-
73
72
disabled_rules. iter ( ) . any ( |r| match r {
74
73
RuleFilter :: Group ( gr) => group. is_some_and ( |specifier_group| specifier_group == * gr) ,
75
74
RuleFilter :: Rule ( gr, ru) => group. is_some_and ( |specifier_group| {
@@ -235,9 +234,8 @@ pub struct Suppressions {
235
234
}
236
235
237
236
impl Suppressions {
237
+ #[ must_use]
238
238
pub fn considering_disabled_rules ( mut self , disabled_rules : & [ RuleFilter < ' _ > ] ) -> Self {
239
- tracing:: error!( "disabled rules: {:#?}" , disabled_rules) ;
240
-
241
239
{
242
240
let ( enabled, disabled) = self
243
241
. file_suppressions
@@ -282,16 +280,64 @@ impl Suppressions {
282
280
self
283
281
}
284
282
285
- pub fn is_suppressed < D : Diagnostic > ( & self , diagnostic : & D ) -> bool {
286
- let location = diagnostic. location ( ) ;
283
+ #[ must_use]
284
+ pub fn with_unused_suppressions_as_errors < D : Diagnostic > ( mut self , diagnostics : & [ D ] ) -> Self {
285
+ let mut diagnostics_by_line: HashMap < usize , Vec < & D > > = HashMap :: new ( ) ;
286
+ for diag in diagnostics {
287
+ if let Some ( line) = diag
288
+ . location ( )
289
+ . span
290
+ . and_then ( |sp| self . line_index . line_for_offset ( sp. start ( ) ) )
291
+ {
292
+ let entry = diagnostics_by_line. entry ( line) ;
293
+ entry
294
+ . and_modify ( |current| {
295
+ current. push ( diag) ;
296
+ } )
297
+ . or_insert ( vec ! [ diag] ) ;
298
+ }
299
+ }
287
300
301
+ for ( line, suppr) in & self . line_suppressions {
302
+ let mut expected_diagnostic_line = line + 1 ;
303
+ while let Some ( _) = self . line_suppressions . get ( & expected_diagnostic_line) {
304
+ expected_diagnostic_line += 1 ;
305
+ }
306
+
307
+ if diagnostics_by_line
308
+ . get ( & expected_diagnostic_line)
309
+ . is_some_and ( |diags| {
310
+ diags. iter ( ) . any ( |d| {
311
+ d. category ( )
312
+ . is_some_and ( |cat| match RuleSpecifier :: try_from ( cat. name ( ) ) {
313
+ Ok ( spec) => suppr. matches ( & spec) ,
314
+ Err ( _) => false ,
315
+ } )
316
+ } )
317
+ } )
318
+ {
319
+ continue ;
320
+ } else {
321
+ self . diagnostics . push ( SuppressionDiagnostic {
322
+ span : suppr. suppression_range ,
323
+ message : MessageAndDescription :: from ( format ! (
324
+ "This suppression has no effect."
325
+ ) ) ,
326
+ } )
327
+ }
328
+ }
329
+
330
+ self
331
+ }
332
+
333
+ pub fn is_suppressed < D : Diagnostic > ( & self , diagnostic : & D ) -> bool {
288
334
diagnostic
289
335
. category ( )
290
336
. map ( |c| match RuleSpecifier :: try_from ( c. name ( ) ) {
291
337
Ok ( specifier) => {
292
338
self . by_file_suppression ( & specifier)
293
- || self . by_range_suppression ( location , & specifier)
294
- || self . by_line_suppression ( location , & specifier)
339
+ || self . by_range_suppression ( diagnostic , & specifier)
340
+ || self . by_line_suppression ( diagnostic , & specifier)
295
341
}
296
342
Err ( _) => false ,
297
343
} )
@@ -302,33 +348,53 @@ impl Suppressions {
302
348
self . file_suppressions . iter ( ) . any ( |s| s. matches ( specifier) )
303
349
}
304
350
305
- fn by_line_suppression ( & self , location : Location < ' _ > , specifier : & RuleSpecifier ) -> bool {
306
- location
351
+ fn by_line_suppression < D : Diagnostic > (
352
+ & self ,
353
+ diagnostic : & D ,
354
+ specifier : & RuleSpecifier ,
355
+ ) -> bool {
356
+ self . get_eligible_line_suppressions_for_diagnostic ( diagnostic)
357
+ . iter ( )
358
+ . any ( |s| s. matches ( specifier) )
359
+ }
360
+
361
+ fn by_range_suppression < D : Diagnostic > (
362
+ & self ,
363
+ diagnostic : & D ,
364
+ specifier : & RuleSpecifier ,
365
+ ) -> bool {
366
+ self . range_suppressions . iter ( ) . any ( |range_suppr| {
367
+ range_suppr. start_suppression . matches ( specifier)
368
+ && diagnostic
369
+ . location ( )
370
+ . span
371
+ . is_some_and ( |sp| range_suppr. suppressed_range . contains_range ( sp) )
372
+ } )
373
+ }
374
+
375
+ fn get_eligible_line_suppressions_for_diagnostic < D : Diagnostic > (
376
+ & self ,
377
+ diagnostic : & D ,
378
+ ) -> Vec < & Suppression > {
379
+ diagnostic
380
+ . location ( )
307
381
. span
308
382
. and_then ( |span| self . line_index . line_for_offset ( span. start ( ) ) )
309
383
. filter ( |line_no| * line_no > 0 )
310
- . is_some_and ( |mut line_no| {
311
- let mut eligible_suppressions = vec ! [ ] ;
384
+ . map ( |mut line_no| {
385
+ let mut eligible = vec ! [ ] ;
312
386
313
387
// one-for-one, we're checking the lines above a diagnostic location
314
388
// until there are no more diagnostics
315
389
line_no -= 1 ;
316
390
while let Some ( suppr) = self . line_suppressions . get ( & line_no) {
317
- eligible_suppressions . push ( suppr) ;
391
+ eligible . push ( suppr) ;
318
392
line_no -= 1 ;
319
393
}
320
394
321
- eligible_suppressions . iter ( ) . any ( |s| s . matches ( specifier ) )
395
+ eligible
322
396
} )
323
- }
324
-
325
- fn by_range_suppression ( & self , location : Location < ' _ > , specifier : & RuleSpecifier ) -> bool {
326
- self . range_suppressions . iter ( ) . any ( |range_suppr| {
327
- range_suppr. start_suppression . matches ( specifier)
328
- && location
329
- . span
330
- . is_some_and ( |sp| range_suppr. suppressed_range . contains_range ( sp) )
331
- } )
397
+ . unwrap_or ( vec ! [ ] )
332
398
}
333
399
}
334
400
0 commit comments