@@ -259,3 +259,109 @@ func FilterRulesFromSarif(sarifData []byte) ([]byte, error) {
259259
260260 return filteredData , nil
261261}
262+
263+ // PyreflyIssue represents a single issue in Pyrefly's JSON output
264+ // Example fields: line, column, stop_line, stop_column, path, code, name, description, concise_description
265+ // See: https://pyrefly.org/en/docs/usage/#output-formats
266+
267+ type PyreflyIssue struct {
268+ Line int `json:"line"`
269+ Column int `json:"column"`
270+ StopLine int `json:"stop_line"`
271+ StopColumn int `json:"stop_column"`
272+ Path string `json:"path"`
273+ Code int `json:"code"`
274+ Name string `json:"name"`
275+ Description string `json:"description"`
276+ ConciseDescription string `json:"concise_description"`
277+ }
278+
279+ // ConvertPyreflyToSarif converts Pyrefly JSON output to SARIF format
280+ func ConvertPyreflyToSarif (pyreflyOutput []byte ) []byte {
281+ // Pyrefly outputs: { "errors": [ ... ] }
282+ type pyreflyRoot struct {
283+ Errors []PyreflyIssue `json:"errors"`
284+ }
285+ var root pyreflyRoot
286+ var sarifReport SarifReport
287+ if err := json .Unmarshal (pyreflyOutput , & root ); err != nil {
288+ // If parsing fails, return empty SARIF report with Pyrefly metadata
289+ sarifReport = SarifReport {
290+ Version : "2.1.0" ,
291+ Schema : "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json" ,
292+ Runs : []Run {
293+ {
294+ Tool : Tool {
295+ Driver : Driver {
296+ Name : "Pyrefly" ,
297+ Version : "0.22.0" ,
298+ InformationURI : "https://pyrefly.org" ,
299+ },
300+ },
301+ Results : []Result {},
302+ },
303+ },
304+ }
305+ } else {
306+ sarifReport = SarifReport {
307+ Version : "2.1.0" ,
308+ Schema : "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json" ,
309+ Runs : []Run {
310+ {
311+ Tool : Tool {
312+ Driver : Driver {
313+ Name : "Pyrefly" ,
314+ Version : "0.22.0" ,
315+ InformationURI : "https://pyrefly.org" ,
316+ },
317+ },
318+ Results : make ([]Result , 0 , len (root .Errors )),
319+ },
320+ },
321+ }
322+ for _ , issue := range root .Errors {
323+ result := Result {
324+ RuleID : issue .Name ,
325+ Level : "error" , // Pyrefly only reports errors
326+ Message : MessageText {
327+ Text : issue .Description ,
328+ },
329+ Locations : []Location {
330+ {
331+ PhysicalLocation : PhysicalLocation {
332+ ArtifactLocation : ArtifactLocation {
333+ URI : issue .Path ,
334+ },
335+ Region : Region {
336+ StartLine : issue .Line ,
337+ StartColumn : issue .Column ,
338+ },
339+ },
340+ },
341+ },
342+ }
343+ sarifReport .Runs [0 ].Results = append (sarifReport .Runs [0 ].Results , result )
344+ }
345+ }
346+ sarifData , err := json .MarshalIndent (sarifReport , "" , " " )
347+ if err != nil {
348+ // If marshaling fails, return a minimal SARIF report with Pyrefly metadata
349+ return []byte (`{
350+ "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
351+ "version": "2.1.0",
352+ "runs": [
353+ {
354+ "tool": {
355+ "driver": {
356+ "name": "Pyrefly",
357+ "version": "0.22.0",
358+ "informationUri": "https://pyrefly.org"
359+ }
360+ },
361+ "results": []
362+ }
363+ ]
364+ }` )
365+ }
366+ return sarifData
367+ }
0 commit comments