From cda7ea3bf591db274392c3619cd82f83bb4f6fbb Mon Sep 17 00:00:00 2001 From: Jonathan Gautheron Date: Thu, 27 Feb 2020 16:08:35 +0100 Subject: [PATCH 1/3] Support function params, ignore backquotes --- go.mod | 3 +++ tests/foo_test.go | 9 +++++++++ tests/main.go | 30 ++++++++++++++++++++++++++++++ visitor.go | 12 +++++++++++- 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 go.mod create mode 100644 tests/foo_test.go create mode 100644 tests/main.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..53dbfbb --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/jgautheron/goconst + +go 1.13 diff --git a/tests/foo_test.go b/tests/foo_test.go new file mode 100644 index 0000000..96395f1 --- /dev/null +++ b/tests/foo_test.go @@ -0,0 +1,9 @@ +package main + +import "fmt" + +func foo() { + foo := "test" + boo := "test" + fmt.Println(foo, boo) +} diff --git a/tests/main.go b/tests/main.go new file mode 100644 index 0000000..227ab61 --- /dev/null +++ b/tests/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "strings" +) + +const Foo = "bar" + +var url string + +func main() { + if strings.HasPrefix(url, "http://") { + url = strings.TrimPrefix(url, "http://") + } + url = strings.TrimPrefix(url, "/") + fmt.Println(url) +} + +func testCase() string { + test := `test` + if url == "test" { + return test + } + switch url { + case "moo": + return "" + } + return "foo" +} diff --git a/visitor.go b/visitor.go index a86421f..27cd5d8 100644 --- a/visitor.go +++ b/visitor.go @@ -95,6 +95,15 @@ func (v *treeVisitor) Visit(node ast.Node) ast.Visitor { v.addString(lit.Value, lit.Pos()) } } + + // fn("http://") + case *ast.CallExpr: + for _, item := range t.Args { + lit, ok := item.(*ast.BasicLit) + if ok && v.isSupported(lit.Kind) { + v.addString(lit.Value, lit.Pos()) + } + } } return v @@ -102,7 +111,8 @@ func (v *treeVisitor) Visit(node ast.Node) ast.Visitor { // addString adds a string in the map along with its position in the tree. func (v *treeVisitor) addString(str string, pos token.Pos) { - str = strings.Replace(str, `"`, "", 2) + // Drop first and last character, quote, backquote... + str = str[1 : len(str)-1] // Ignore empty strings if len(str) == 0 { From bb08b627f7f8ae1ddcd2ce6d1197e49acf83949e Mon Sep 17 00:00:00 2001 From: golangci Date: Mon, 7 May 2018 12:41:31 +0300 Subject: [PATCH 2/3] make API --- parser.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/parser.go b/parser.go index 5f83723..f1bc4b2 100644 --- a/parser.go +++ b/parser.go @@ -134,3 +134,54 @@ type ExtendedPos struct { token.Position packageName string } + +type Issue struct { + Pos token.Position + OccurencesCount int + Str string + MatchingConst string +} + +func Run(files []string, matchWithConstants bool, minStringLength, minOccurrences int) ([]Issue, error) { + p := New("", "", false, matchWithConstants, false, minStringLength) + var issues []Issue + fset := token.NewFileSet() + for _, path := range files { + f, err := parser.ParseFile(fset, path, nil, 0) + if err != nil { + return nil, err + } + ast.Walk(&treeVisitor{ + fileSet: fset, + packageName: "", + fileName: path, + p: p, + }, f) + } + + for str, item := range p.strs { + // Filter out items whose occurrences don't match the min value + if len(item) < minOccurrences { + delete(p.strs, str) + } + } + + for str, item := range p.strs { + fi := item[0] + i := Issue{ + Pos: fi.Position, + OccurencesCount: len(item), + Str: str, + } + + if len(p.consts) != 0 { + if cst, ok := p.consts[str]; ok { + // const should be in the same package and exported + i.MatchingConst = cst.Name + } + } + issues = append(issues, i) + } + + return issues, nil +} From b7b936e9134b60d960e23910c7c36fe712fedeed Mon Sep 17 00:00:00 2001 From: golangci Date: Sun, 10 Jun 2018 17:16:41 +0300 Subject: [PATCH 3/3] accept ast.File-s --- parser.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/parser.go b/parser.go index f1bc4b2..ab5f99a 100644 --- a/parser.go +++ b/parser.go @@ -142,26 +142,27 @@ type Issue struct { MatchingConst string } -func Run(files []string, matchWithConstants bool, minStringLength, minOccurrences int) ([]Issue, error) { - p := New("", "", false, matchWithConstants, false, minStringLength) +type Config struct { + MatchWithConstants bool + MinStringLength int + MinOccurrences int +} + +func Run(files []*ast.File, fset *token.FileSet, cfg *Config) ([]Issue, error) { + p := New("", "", false, cfg.MatchWithConstants, false, cfg.MinStringLength) var issues []Issue - fset := token.NewFileSet() - for _, path := range files { - f, err := parser.ParseFile(fset, path, nil, 0) - if err != nil { - return nil, err - } + for _, f := range files { ast.Walk(&treeVisitor{ fileSet: fset, packageName: "", - fileName: path, + fileName: "", p: p, }, f) } for str, item := range p.strs { // Filter out items whose occurrences don't match the min value - if len(item) < minOccurrences { + if len(item) < cfg.MinOccurrences { delete(p.strs, str) } }