From 5110205d09e23cc943202511e039a4ce6183ff84 Mon Sep 17 00:00:00 2001 From: Marcin Federowicz Date: Wed, 1 Nov 2023 23:57:46 +0100 Subject: [PATCH] extend parsing instructions to use json object instead of plain txt --- test/json-data-format_test.go | 17 ++++++ test/utils.go | 70 +++++++++++++++++++++++-- testdata/json-data-format-atomic.go | 13 +++++ testdata/json-data-format-var-naming.go | 8 +++ 4 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 test/json-data-format_test.go create mode 100644 testdata/json-data-format-atomic.go create mode 100644 testdata/json-data-format-var-naming.go diff --git a/test/json-data-format_test.go b/test/json-data-format_test.go new file mode 100644 index 000000000..3914b3155 --- /dev/null +++ b/test/json-data-format_test.go @@ -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{}) + +} diff --git a/test/utils.go b/test/utils.go index 0b3b0bd4d..af8b60a32 100644 --- a/test/utils.go +++ b/test/utils.go @@ -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 +} + +// 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 { diff --git a/testdata/json-data-format-atomic.go b/testdata/json-data-format-atomic.go new file mode 100644 index 000000000..23f73f18a --- /dev/null +++ b/testdata/json-data-format-atomic.go @@ -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) + +} diff --git a/testdata/json-data-format-var-naming.go b/testdata/json-data-format-var-naming.go new file mode 100644 index 000000000..fef852203 --- /dev/null +++ b/testdata/json-data-format-var-naming.go @@ -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 +}