github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/linter/report/reporters/sarifReporter.go (about) 1 package reporters 2 3 import ( 4 "io" 5 6 "github.com/chavacava/garif" 7 "github.com/yoheimuta/protolint/linter/report" 8 "github.com/yoheimuta/protolint/linter/rule" 9 ) 10 11 // SarifReporter creates reports formatted as a JSON 12 // Document. 13 // The document format is used according to the SARIF 14 // Standard. 15 // Refer to http://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html 16 // for details to the format. 17 type SarifReporter struct{} 18 19 var allSeverities map[string]rule.Severity = map[string]rule.Severity{ 20 string(rule.SeverityError): rule.SeverityError, 21 string(rule.SeverityWarning): rule.SeverityWarning, 22 string(rule.SeverityNote): rule.SeverityNote, 23 } 24 25 func contains(s []string, e string) bool { 26 for _, a := range s { 27 if a == e { 28 return true 29 } 30 } 31 return false 32 } 33 34 // Report writes failures to w formatted as a SARIF document. 35 func (r SarifReporter) Report(w io.Writer, fs []report.Failure) error { 36 rulesByID := make(map[string]*garif.ReportingDescriptor) 37 allRules := []*garif.ReportingDescriptor{} 38 artifactLocations := []string{} 39 40 tool := garif.NewDriver("protolint"). 41 WithInformationUri("https://github.com/yoheimuta/protolint") 42 43 run := garif.NewRun(garif.NewTool(tool)) 44 45 for _, failure := range fs { 46 _, ruleFound := rulesByID[failure.RuleID()] 47 if !ruleFound { 48 rule := garif.NewRule( 49 failure.RuleID(), 50 ). 51 WithHelpUri("https://github.com/yoheimuta/protolint") 52 53 rulesByID[failure.RuleID()] = rule 54 allRules = append(allRules, rule) 55 } 56 57 if !(contains(artifactLocations, failure.Pos().Filename)) { 58 artifactLocations = append(artifactLocations, failure.Pos().Filename) 59 } 60 61 run.WithResult( 62 failure.RuleID(), 63 failure.Message(), 64 failure.Pos().Filename, 65 failure.Pos().Line, 66 failure.Pos().Column, 67 ) 68 69 if len(run.Results) > 0 { 70 71 recentResult := run.Results[len(run.Results)-1] 72 recentResult.Kind = garif.ResultKind_Fail 73 74 if lvl, ok := allSeverities[failure.Severity()]; ok { 75 recentResult.Level = getResultLevel(lvl) 76 } 77 } 78 } 79 80 tool.WithRules(allRules...) 81 run.WithArtifactsURIs(artifactLocations...) 82 83 logFile := garif.NewLogFile([]*garif.Run{run}, garif.Version210) 84 return logFile.PrettyWrite(w) 85 } 86 87 func getResultLevel(severity rule.Severity) garif.ResultLevel { 88 switch severity { 89 case rule.SeverityError: 90 return garif.ResultLevel_Error 91 case rule.SeverityWarning: 92 return garif.ResultLevel_Warning 93 case rule.SeverityNote: 94 return garif.ResultLevel_None 95 } 96 97 return garif.ResultLevel_None 98 }