1
0
mirror of https://github.com/mgechev/revive.git synced 2025-01-06 03:04:06 +02:00

extend parsing instructions to use json object instead of plain txt (#929)

This commit is contained in:
Marcin Federowicz 2023-11-26 10:18:36 +01:00 committed by GitHub
parent 9a2eab34f1
commit 9e80d93545
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 103 additions and 5 deletions

View File

@ -0,0 +1,17 @@
package test
import (
"testing"
"github.com/mgechev/revive/lint"
"github.com/mgechev/revive/rule"
)
func TestJsonDataFormat(t *testing.T) {
testRule(t, "json-data-format-atomic", &rule.AtomicRule{})
}
func TestJsonDataFormatVarNaming(t *testing.T) {
testRule(t, "json-data-format-var-naming", &rule.VarNamingRule{}, &lint.RuleConfig{})
}

View File

@ -3,6 +3,7 @@ package test
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"go/ast"
"go/parser"
@ -89,6 +90,7 @@ func assertFailures(t *testing.T, baseDir string, fi os.FileInfo, src []byte, ru
if p.Position.Start.Line != in.Line {
continue
}
if in.Match == p.Failure {
// check replacement if we are expecting one
if in.Replacement != "" {
@ -102,6 +104,14 @@ func assertFailures(t *testing.T, baseDir string, fi os.FileInfo, src []byte, ru
}
}
if in.Confidence > 0 {
if in.Confidence != p.Confidence {
t.Errorf("Lint failed at %s:%d; got confidence %f, want %f", fi.Name(), in.Line, p.Confidence, in.Confidence)
}
}
// remove this problem from ps
copy(failures[i:], failures[i+1:])
failures = failures[:len(failures)-1]
@ -122,9 +132,19 @@ func assertFailures(t *testing.T, baseDir string, fi os.FileInfo, src []byte, ru
}
type instruction struct {
Line int // the line number this applies to
Match string // which pattern to match
Replacement string // what the suggested replacement line should be
Line int // the line number this applies to
Match string // which pattern to match
Replacement string // what the suggested replacement line should be
RuleName string // what rule we use
Category string // which category
Confidence float64 // confidence level
}
// JSONInstruction structure used when we parse json object insted of classic MATCH string
type JSONInstruction struct {
Match string `json:"MATCH"`
Category string `json:"Category"`
Confidence float64 `json:"Confidence"`
}
// parseInstructions parses instructions from the comments in a Go source file.
@ -140,7 +160,7 @@ func parseInstructions(t *testing.T, filename string, src []byte) []instruction
ln := fset.Position(cg.Pos()).Line
raw := cg.Text()
for _, line := range strings.Split(raw, "\n") {
if line == "" || strings.HasPrefix(line, "#") {
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, "ignore") {
continue
}
if line == "OK" && ins == nil {
@ -148,7 +168,15 @@ func parseInstructions(t *testing.T, filename string, src []byte) []instruction
ins = make([]instruction, 0)
continue
}
if strings.Contains(line, "MATCH") {
switch extractDataMode(line) {
case "json":
jsonInst, err := extractInstructionFromJSON(strings.TrimPrefix(line, "json:"), ln)
if err != nil {
t.Fatalf("At %v:%d: %v", filename, ln, err)
}
ins = append(ins, jsonInst)
break
case "classic":
match, err := extractPattern(line)
if err != nil {
t.Fatalf("At %v:%d: %v", filename, ln, err)
@ -172,12 +200,44 @@ func parseInstructions(t *testing.T, filename string, src []byte) []instruction
Match: match,
Replacement: repl,
})
break
}
}
}
return ins
}
func extractInstructionFromJSON(line string, lineNumber int) (instruction, error) {
// Use the json.Unmarshal function to parse the JSON into the struct
var jsonInst JSONInstruction
if err := json.Unmarshal([]byte(line), &jsonInst); err != nil {
fmt.Println("Error parsing JSON:", err)
}
ins := instruction{
Match: jsonInst.Match,
Confidence: jsonInst.Confidence,
Category: jsonInst.Category,
Line: lineNumber,
}
return ins, nil
}
func extractDataMode(line string) string {
if strings.HasPrefix(line, "json") {
return "json"
}
if strings.Contains(line, "MATCH") {
return "classic"
}
return ""
}
func extractPattern(line string) (string, error) {
a, b := strings.Index(line, "/"), strings.LastIndex(line, "/")
if a == -1 || a == b {

13
testdata/json-data-format-atomic.go vendored Normal file
View File

@ -0,0 +1,13 @@
package fixtures
import (
"sync/atomic"
)
type Counter uint64
func AtomicTests() {
x = atomic.AddUint64(&x, 1) // json:{"MATCH": "direct assignment to atomic value","Confidence": 1}
x := uint64(1)
}

View File

@ -0,0 +1,8 @@
package fixtures
func foo() string {
customID := "result" // ignore
customVm := "result" // json:{"MATCH": "var customVm should be customVM"}
CUSTOMER_UP := "result" // json:{"MATCH": "don't use ALL_CAPS in Go names; use CamelCase", "Confidence": 0.8}
return customId
}