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/parser.go b/parser.go index 5f83723..ab5f99a 100644 --- a/parser.go +++ b/parser.go @@ -134,3 +134,55 @@ type ExtendedPos struct { token.Position packageName string } + +type Issue struct { + Pos token.Position + OccurencesCount int + Str string + MatchingConst string +} + +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 + for _, f := range files { + ast.Walk(&treeVisitor{ + fileSet: fset, + packageName: "", + fileName: "", + p: p, + }, f) + } + + for str, item := range p.strs { + // Filter out items whose occurrences don't match the min value + if len(item) < cfg.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 +} 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 {