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  }