mirror of
https://github.com/mgechev/revive.git
synced 2025-11-29 22:28:23 +02:00
extend parsing instructions to use json object instead of plain txt (#929)
This commit is contained in:
committed by
GitHub
parent
9a2eab34f1
commit
9e80d93545
17
test/json-data-format_test.go
Normal file
17
test/json-data-format_test.go
Normal 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{})
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package test
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/parser"
|
"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 {
|
if p.Position.Start.Line != in.Line {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if in.Match == p.Failure {
|
if in.Match == p.Failure {
|
||||||
// check replacement if we are expecting one
|
// check replacement if we are expecting one
|
||||||
if in.Replacement != "" {
|
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
|
// remove this problem from ps
|
||||||
copy(failures[i:], failures[i+1:])
|
copy(failures[i:], failures[i+1:])
|
||||||
failures = failures[:len(failures)-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 {
|
type instruction struct {
|
||||||
Line int // the line number this applies to
|
Line int // the line number this applies to
|
||||||
Match string // which pattern to match
|
Match string // which pattern to match
|
||||||
Replacement string // what the suggested replacement line should be
|
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.
|
// 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
|
ln := fset.Position(cg.Pos()).Line
|
||||||
raw := cg.Text()
|
raw := cg.Text()
|
||||||
for _, line := range strings.Split(raw, "\n") {
|
for _, line := range strings.Split(raw, "\n") {
|
||||||
if line == "" || strings.HasPrefix(line, "#") {
|
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, "ignore") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if line == "OK" && ins == nil {
|
if line == "OK" && ins == nil {
|
||||||
@@ -148,7 +168,15 @@ func parseInstructions(t *testing.T, filename string, src []byte) []instruction
|
|||||||
ins = make([]instruction, 0)
|
ins = make([]instruction, 0)
|
||||||
continue
|
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)
|
match, err := extractPattern(line)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("At %v:%d: %v", filename, ln, err)
|
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,
|
Match: match,
|
||||||
Replacement: repl,
|
Replacement: repl,
|
||||||
})
|
})
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ins
|
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) {
|
func extractPattern(line string) (string, error) {
|
||||||
a, b := strings.Index(line, "/"), strings.LastIndex(line, "/")
|
a, b := strings.Index(line, "/"), strings.LastIndex(line, "/")
|
||||||
if a == -1 || a == b {
|
if a == -1 || a == b {
|
||||||
|
|||||||
13
testdata/json-data-format-atomic.go
vendored
Normal file
13
testdata/json-data-format-atomic.go
vendored
Normal 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)
|
||||||
|
|
||||||
|
}
|
||||||
8
testdata/json-data-format-var-naming.go
vendored
Normal file
8
testdata/json-data-format-var-naming.go
vendored
Normal 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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user