github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/formatter/sarif.go (about) 1 package formatter 2 3 import ( 4 "bytes" 5 "fmt" 6 "strings" 7 8 "github.com/chavacava/garif" 9 "github.com/mgechev/revive/lint" 10 ) 11 12 // Sarif is an implementation of the Formatter interface 13 // which formats revive failures into SARIF format. 14 type Sarif struct { 15 Metadata lint.FormatterMetadata 16 } 17 18 // Name returns the name of the formatter 19 func (f *Sarif) Name() string { 20 return "sarif" 21 } 22 23 const reviveSite = "https://revive.run" 24 25 // Format formats the failures gotten from the lint. 26 func (f *Sarif) Format(failures <-chan lint.Failure, cfg lint.Config) (string, error) { 27 sarifLog := newReviveRunLog(cfg) 28 29 for failure := range failures { 30 sarifLog.AddResult(failure) 31 } 32 33 buf := new(bytes.Buffer) 34 sarifLog.PrettyWrite(buf) 35 36 return buf.String(), nil 37 } 38 39 type reviveRunLog struct { 40 *garif.LogFile 41 run *garif.Run 42 rules map[string]lint.RuleConfig 43 } 44 45 func newReviveRunLog(cfg lint.Config) *reviveRunLog { 46 run := garif.NewRun(garif.NewTool(garif.NewDriver("revive").WithInformationUri(reviveSite))) 47 log := garif.NewLogFile([]*garif.Run{run}, garif.Version210) 48 49 reviveLog := &reviveRunLog{ 50 log, 51 run, 52 cfg.Rules, 53 } 54 55 reviveLog.addRules(cfg.Rules) 56 57 return reviveLog 58 } 59 60 func (l *reviveRunLog) addRules(cfg map[string]lint.RuleConfig) { 61 for name, ruleCfg := range cfg { 62 rule := garif.NewRule(name).WithHelpUri(reviveSite + "/r#" + name) 63 setRuleProperties(rule, ruleCfg) 64 driver := l.run.Tool.Driver 65 66 if driver.Rules == nil { 67 driver.Rules = []*garif.ReportingDescriptor{rule} 68 return 69 } 70 71 driver.Rules = append(driver.Rules, rule) 72 } 73 } 74 75 func (l *reviveRunLog) AddResult(failure lint.Failure) { 76 positiveOrZero := func(x int) int { 77 if x > 0 { 78 return x 79 } 80 return 0 81 } 82 position := failure.Position 83 filename := position.Start.Filename 84 line := positiveOrZero(position.Start.Line - 1) // https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#def_line 85 column := positiveOrZero(position.Start.Column - 1) // https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#def_column 86 87 result := garif.NewResult(garif.NewMessageFromText(failure.Failure)) 88 location := garif.NewLocation().WithURI(filename).WithLineColumn(line, column) 89 result.Locations = append(result.Locations, location) 90 result.RuleId = failure.RuleName 91 result.Level = l.rules[failure.RuleName].Severity 92 93 l.run.Results = append(l.run.Results, result) 94 } 95 96 func setRuleProperties(sarifRule *garif.ReportingDescriptor, lintRule lint.RuleConfig) { 97 arguments := make([]string, len(lintRule.Arguments)) 98 for i, arg := range lintRule.Arguments { 99 arguments[i] = fmt.Sprintf("%+v", arg) 100 } 101 102 if len(arguments) > 0 { 103 sarifRule.WithProperties("arguments", strings.Join(arguments, ",")) 104 } 105 106 sarifRule.WithProperties("severity", string(lintRule.Severity)) 107 }