11use crate :: diag:: Extra ;
22use crate :: sarif:: model:: {
3- DefaultConfiguration , Driver , Help , Location , Message , Result as SarifResult , Rule ,
4- RuleProperties , Run , SarifLog , TextContent , Tool ,
3+ ArtifactLocation , DefaultConfiguration , Driver , Help , Location , Message , PhysicalLocation ,
4+ Region , Result as SarifResult , Rule , RuleProperties , Run , SarifLog , TextContent , Tool ,
55} ;
66use crate :: {
77 Kid ,
@@ -14,6 +14,7 @@ use std::fmt::Write as _;
1414pub struct SarifCollector {
1515 diagnostics : Vec < DiagnosticData > ,
1616 rules : BTreeMap < DiagnosticCode , RuleData > ,
17+ workspace_root : String ,
1718}
1819
1920struct DiagnosticData {
@@ -31,17 +32,15 @@ struct RuleData {
3132 description : & ' static str ,
3233}
3334
34- #[ allow( clippy:: derivable_impls) ]
35- impl Default for SarifCollector {
36- fn default ( ) -> Self {
35+ impl SarifCollector {
36+ pub fn new ( workspace_root : impl Into < String > ) -> Self {
3737 Self {
3838 diagnostics : Vec :: new ( ) ,
3939 rules : BTreeMap :: new ( ) ,
40+ workspace_root : workspace_root. into ( ) ,
4041 }
4142 }
42- }
4343
44- impl SarifCollector {
4544 pub fn add_diagnostics ( & mut self , pack : Pack , files : & crate :: diag:: Files ) {
4645 for diag in pack {
4746 let Some ( code) = diag. code else {
@@ -255,11 +254,37 @@ impl SarifCollector {
255254 }
256255 }
257256
257+ // GitHub Code Scanning requires at least one location per result.
258+ // If no locations were found (e.g., for dependency advisories that only
259+ // reference Cargo.lock which is filtered out), add a fallback location
260+ // pointing to the workspace Cargo.toml since that's where dependencies are declared.
261+ let locations = if diag. locations . is_empty ( ) {
262+ let fallback_uri = if self . workspace_root . is_empty ( ) {
263+ "Cargo.toml" . to_string ( )
264+ } else {
265+ format ! ( "{}/Cargo.toml" , self . workspace_root)
266+ } ;
267+ vec ! [ Location {
268+ physical_location: PhysicalLocation {
269+ artifact_location: ArtifactLocation { uri: fallback_uri } ,
270+ region: Region {
271+ start_line: 1 ,
272+ byte_offset: 0 ,
273+ byte_length: 0 ,
274+ snippet: None ,
275+ message: None ,
276+ } ,
277+ } ,
278+ } ]
279+ } else {
280+ diag. locations
281+ } ;
282+
258283 SarifResult {
259284 rule_id,
260285 message : diag. message ,
261286 level : severity_to_sarif_level ( diag. severity ) ,
262- locations : diag . locations ,
287+ locations,
263288 partial_fingerprints : fingerprints,
264289 }
265290 } )
0 commit comments