16
16
import java .util .Optional ;
17
17
import java .util .Set ;
18
18
import java .util .TreeSet ;
19
- import java .util .function .Function ;
20
19
import java .util .stream .Collectors ;
21
20
import se .bjurr .violations .lib .ViolationsLogger ;
22
21
import se .bjurr .violations .lib .model .SEVERITY ;
31
30
import se .bjurr .violations .lib .model .generated .sarif .Region ;
32
31
import se .bjurr .violations .lib .model .generated .sarif .ReportingConfiguration ;
33
32
import se .bjurr .violations .lib .model .generated .sarif .ReportingDescriptor ;
33
+ import se .bjurr .violations .lib .model .generated .sarif .ReportingDescriptorReference ;
34
34
import se .bjurr .violations .lib .model .generated .sarif .Result ;
35
35
import se .bjurr .violations .lib .model .generated .sarif .Result .Level ;
36
36
import se .bjurr .violations .lib .model .generated .sarif .Run ;
37
37
import se .bjurr .violations .lib .model .generated .sarif .SarifSchema ;
38
+ import se .bjurr .violations .lib .model .generated .sarif .ToolComponent ;
39
+ import se .bjurr .violations .lib .model .generated .sarif .ToolComponentReference ;
38
40
import se .bjurr .violations .lib .reports .Parser ;
39
41
import se .bjurr .violations .lib .util .Utils ;
40
42
41
43
public class SarifParser implements ViolationsParser {
44
+ /** 3.52.3 */
45
+ public enum DescriptorElementOf {
46
+ RULES ,
47
+ NOTIFICATIONS
48
+ }
49
+
42
50
public static final String SARIF_RESULTS_CORRELATION_GUID = "correlationGuid" ;
43
51
44
52
public class ParsedPhysicalLocation {
@@ -127,7 +135,6 @@ ReportingConfiguration.Level.class, new ReportingConfigurationDeserializer())
127
135
128
136
private Set <Violation > parseResults (final Run run ) {
129
137
final Set <Violation > violations = new TreeSet <>();
130
- final Map <String , ReportingDescriptor > rulesById = this .getRulesById (run );
131
138
final String reporter = this .getReporter (run );
132
139
for (final Result result : run .getResults ()) {
133
140
final String ruleId = result .getRuleId ();
@@ -143,8 +150,8 @@ private Set<Violation> parseResults(final Run run) {
143
150
if (!isNullOrEmpty (correlationGuid )) {
144
151
specifics .put (SARIF_RESULTS_CORRELATION_GUID , correlationGuid );
145
152
}
146
-
147
- final ReportingDescriptor reportingDescriptor = rulesById . get ( ruleId );
153
+ final ReportingDescriptor reportingDescriptor =
154
+ this . findReportingDescriptor ( run , result , DescriptorElementOf . RULES ). orElse ( null );
148
155
final String category = this .getCategory (reportingDescriptor );
149
156
150
157
final Optional <String > helpTextOpt = this .findHelpText (reportingDescriptor );
@@ -189,12 +196,19 @@ private Set<Violation> parseResults(final Run run) {
189
196
190
197
private Set <Violation > parseNotifications (final Run run ) {
191
198
final Set <Violation > violations = new TreeSet <>();
192
- final List < ReportingDescriptor > notifications = this .getNotifications (run );
199
+ this .getNotifications (run );
193
200
final String reporter = this .getReporter (run );
194
201
for (final Invocation invocation : run .getInvocations ()) {
195
202
for (final Notification notification : invocation .getToolConfigurationNotifications ()) {
203
+ notification .getAssociatedRule ();
204
+ final ReportingDescriptorReference ref = notification .getAssociatedRule ();
205
+ final Integer ruleIndex = this .getRuleIndex (ref );
206
+ final String ruleId = null ;
196
207
final ReportingDescriptor reportingDescriptor =
197
- this .getReportingDescriptor (notifications , notification );
208
+ this .findReportingDescriptor (
209
+ run , DescriptorElementOf .NOTIFICATIONS , ref , ruleIndex , ruleId )
210
+ .orElse (null );
211
+
198
212
final String reportingDescriptorName = this .getName (reportingDescriptor );
199
213
final SEVERITY severity = this .toSeverity (notification .getLevel (), reportingDescriptor );
200
214
final List <Location > locations = this .filter (notification .getLocations ());
@@ -237,6 +251,17 @@ private Set<Violation> parseNotifications(final Run run) {
237
251
return violations ;
238
252
}
239
253
254
+ private Integer getRuleIndex (final ReportingDescriptorReference ref ) {
255
+ Integer ruleIndex = null ;
256
+ if (ref != null ) {
257
+ ruleIndex = ref .getIndex ();
258
+ }
259
+ if (ruleIndex == null || ruleIndex == -1 ) {
260
+ return null ;
261
+ }
262
+ return ruleIndex ;
263
+ }
264
+
240
265
private String getName (final ReportingDescriptor reportingDescriptor ) {
241
266
if (reportingDescriptor != null ) {
242
267
return reportingDescriptor .getName ();
@@ -295,18 +320,6 @@ private List<Location> filterLocations(final List<Location> locations) {
295
320
.collect (Collectors .toList ());
296
321
}
297
322
298
- private ReportingDescriptor getReportingDescriptor (
299
- final List <ReportingDescriptor > notifications , final Notification notification ) {
300
- if (notification .getDescriptor () == null ) {
301
- return null ;
302
- }
303
- final Integer notificationIndex = notification .getDescriptor ().getIndex ();
304
- if (notificationIndex == null ) {
305
- return null ;
306
- }
307
- return notifications .get (notificationIndex );
308
- }
309
-
310
323
private String toMessage (
311
324
final Message message ,
312
325
final Optional <String > helpTextOpt ,
@@ -392,16 +405,6 @@ private String extractMessage(
392
405
return "" ;
393
406
}
394
407
395
- private Map <String , ReportingDescriptor > getRulesById (final Run run ) {
396
- if (run .getTool () != null
397
- && run .getTool ().getDriver () != null
398
- && run .getTool ().getDriver ().getRules () != null ) {
399
- return run .getTool ().getDriver ().getRules ().stream ()
400
- .collect (Collectors .toMap (ReportingDescriptor ::getId , Function .identity ()));
401
- }
402
- return new HashMap <>();
403
- }
404
-
405
408
private Optional <String > findHelpText (final ReportingDescriptor r ) {
406
409
if (r == null ) {
407
410
return Optional .empty ();
@@ -461,4 +464,115 @@ private Optional<SEVERITY> toSeverity(final ReportingDescriptor reportingDescrip
461
464
}
462
465
return Optional .empty ();
463
466
}
467
+
468
+ private Optional <ReportingDescriptor > findReportingDescriptor (
469
+ final Run run , final Result result , final DescriptorElementOf lookIn ) {
470
+ final ReportingDescriptorReference ref = result .getRule ();
471
+ final Integer ruleIndex = this .findRuleIndex (result , ref );
472
+ final String ruleId = result .getRuleId ();
473
+ return this .findReportingDescriptor (run , lookIn , ref , ruleIndex , ruleId );
474
+ }
475
+
476
+ private Optional <ReportingDescriptor > findReportingDescriptor (
477
+ final Run run ,
478
+ final DescriptorElementOf lookIn ,
479
+ final ReportingDescriptorReference ref ,
480
+ final Integer ruleIndex ,
481
+ final String ruleId ) {
482
+ final ToolComponent tool = this .findToolComponent (run , ref );
483
+ if (tool == null ) {
484
+ return Optional .empty ();
485
+ }
486
+ if (ruleIndex != null ) {
487
+ return Optional .of (this .getReportingDescriptorByIndex (tool , ruleIndex , lookIn ));
488
+ }
489
+
490
+ if (ref != null && ref .getGuid () != null ) {
491
+ return this .findReportingDescriptorByGui (tool , ref .getGuid (), lookIn );
492
+ }
493
+ if (ruleId != null ) {
494
+ return this .findReportingDescriptorByRuleId (tool , ruleId , lookIn );
495
+ }
496
+ return Optional .empty ();
497
+ }
498
+
499
+ private Integer findRuleIndex (final Result result , final ReportingDescriptorReference ref ) {
500
+ Integer ruleIndex = result .getRuleIndex ();
501
+ if (ruleIndex == -1 ) {
502
+ ruleIndex = null ;
503
+ }
504
+ if (ruleIndex == null && ref != null ) {
505
+ ruleIndex = ref .getIndex ();
506
+ }
507
+ return ruleIndex ;
508
+ }
509
+
510
+ private ToolComponent findToolComponent (final Run run , final ReportingDescriptorReference ref ) {
511
+ if (run .getTool () == null ) {
512
+ return null ;
513
+ }
514
+ if (ref == null ) {
515
+ return run .getTool ().getDriver ();
516
+ }
517
+ final ToolComponentReference toolRef = ref .getToolComponent ();
518
+ if (toolRef .getGuid () != null ) {
519
+ return this .getToolComponentByGui (run , toolRef .getGuid ());
520
+ }
521
+ if (toolRef .getIndex () != null ) {
522
+ return this .getToolComponentByIndex (run , toolRef .getIndex ());
523
+ }
524
+ return run .getTool ().getDriver ();
525
+ }
526
+
527
+ private ReportingDescriptor getReportingDescriptorByIndex (
528
+ final ToolComponent tool , final Integer index , final DescriptorElementOf lookIn ) {
529
+ if (lookIn == DescriptorElementOf .RULES ) {
530
+ return new ArrayList <>(tool .getRules ()).get (index );
531
+ }
532
+ if (lookIn == DescriptorElementOf .NOTIFICATIONS ) {
533
+ return new ArrayList <>(tool .getNotifications ()).get (index );
534
+ }
535
+ throw new IllegalStateException (lookIn + " cannot find ReportingDescriptor" );
536
+ }
537
+
538
+ private Optional <ReportingDescriptor > findReportingDescriptorByGui (
539
+ final ToolComponent tool , final String guid , final DescriptorElementOf lookIn ) {
540
+ if (lookIn == DescriptorElementOf .RULES ) {
541
+ return tool .getRules ().stream ()
542
+ .filter ((it ) -> it .getGuid () != null && it .getGuid ().equals (guid ))
543
+ .findFirst ();
544
+ }
545
+ if (lookIn == DescriptorElementOf .NOTIFICATIONS ) {
546
+ return tool .getNotifications ().stream ()
547
+ .filter ((it ) -> it .getGuid () != null && it .getGuid ().equals (guid ))
548
+ .findFirst ();
549
+ }
550
+ return Optional .empty ();
551
+ }
552
+
553
+ private Optional <ReportingDescriptor > findReportingDescriptorByRuleId (
554
+ final ToolComponent tool , final String ruleId , final DescriptorElementOf lookIn ) {
555
+ if (lookIn == DescriptorElementOf .RULES ) {
556
+ return tool .getRules ().stream ()
557
+ .filter ((it ) -> it .getId () != null && it .getId ().equals (ruleId ))
558
+ .findFirst ();
559
+ }
560
+ if (lookIn == DescriptorElementOf .NOTIFICATIONS ) {
561
+ return tool .getNotifications ().stream ()
562
+ .filter ((it ) -> it .getId () != null && it .getId ().equals (ruleId ))
563
+ .findFirst ();
564
+ }
565
+ throw new IllegalStateException (lookIn + " cannot find ReportingDescriptor" );
566
+ }
567
+
568
+ private ToolComponent getToolComponentByIndex (final Run run , final Integer index ) {
569
+ return new ArrayList <>(run .getTool ().getExtensions ()).get (index );
570
+ }
571
+
572
+ private ToolComponent getToolComponentByGui (final Run run , final String guid ) {
573
+ return run .getTool ().getExtensions ().stream ()
574
+ .filter ((it ) -> it .getGuid () != null && it .getGuid ().equals (guid ))
575
+ .findFirst ()
576
+ .get ();
577
+ }
464
578
}
0 commit comments