aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/golangci/dupl/main.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-07-04 11:12:55 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-07-04 15:05:30 +0200
commitc7d7f10bdff703e4a3c0414e8a33d4e45c91eb35 (patch)
tree0dff0ee1f98dbfa3ad8776112053a450d176592b /vendor/github.com/golangci/dupl/main.go
parent9573094ce235bd9afe88f5da27a47dd6bcc1e13b (diff)
go.mod: vendor golangci-lint
Diffstat (limited to 'vendor/github.com/golangci/dupl/main.go')
-rw-r--r--vendor/github.com/golangci/dupl/main.go148
1 files changed, 148 insertions, 0 deletions
diff --git a/vendor/github.com/golangci/dupl/main.go b/vendor/github.com/golangci/dupl/main.go
new file mode 100644
index 000000000..3030a97ae
--- /dev/null
+++ b/vendor/github.com/golangci/dupl/main.go
@@ -0,0 +1,148 @@
+package dupl
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sort"
+
+ "github.com/golangci/dupl/job"
+ "github.com/golangci/dupl/printer"
+ "github.com/golangci/dupl/syntax"
+)
+
+const defaultThreshold = 15
+
+var (
+ paths = []string{"."}
+ vendor = flag.Bool("dupl.vendor", false, "")
+ verbose = flag.Bool("dupl.verbose", false, "")
+ files = flag.Bool("dupl.files", false, "")
+
+ html = flag.Bool("dupl.html", false, "")
+ plumbing = flag.Bool("dupl.plumbing", false, "")
+)
+
+const (
+ vendorDirPrefix = "vendor" + string(filepath.Separator)
+ vendorDirInPath = string(filepath.Separator) + vendorDirPrefix
+)
+
+func init() {
+ flag.BoolVar(verbose, "dupl.v", false, "alias for -verbose")
+}
+
+func Run(files []string, threshold int) ([]printer.Issue, error) {
+ fchan := make(chan string, 1024)
+ go func() {
+ for _, f := range files {
+ fchan <- f
+ }
+ close(fchan)
+ }()
+ schan := job.Parse(fchan)
+ t, data, done := job.BuildTree(schan)
+ <-done
+
+ // finish stream
+ t.Update(&syntax.Node{Type: -1})
+
+ mchan := t.FindDuplOver(threshold)
+ duplChan := make(chan syntax.Match)
+ go func() {
+ for m := range mchan {
+ match := syntax.FindSyntaxUnits(*data, m, threshold)
+ if len(match.Frags) > 0 {
+ duplChan <- match
+ }
+ }
+ close(duplChan)
+ }()
+
+ return makeIssues(duplChan)
+}
+
+func makeIssues(duplChan <-chan syntax.Match) ([]printer.Issue, error) {
+ groups := make(map[string][][]*syntax.Node)
+ for dupl := range duplChan {
+ groups[dupl.Hash] = append(groups[dupl.Hash], dupl.Frags...)
+ }
+ keys := make([]string, 0, len(groups))
+ for k := range groups {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+
+ p := printer.NewPlumbing(ioutil.ReadFile)
+
+ var issues []printer.Issue
+ for _, k := range keys {
+ uniq := unique(groups[k])
+ if len(uniq) > 1 {
+ i, err := p.MakeIssues(uniq)
+ if err != nil {
+ return nil, err
+ }
+ issues = append(issues, i...)
+ }
+ }
+
+ return issues, nil
+}
+
+func unique(group [][]*syntax.Node) [][]*syntax.Node {
+ fileMap := make(map[string]map[int]struct{})
+
+ var newGroup [][]*syntax.Node
+ for _, seq := range group {
+ node := seq[0]
+ file, ok := fileMap[node.Filename]
+ if !ok {
+ file = make(map[int]struct{})
+ fileMap[node.Filename] = file
+ }
+ if _, ok := file[node.Pos]; !ok {
+ file[node.Pos] = struct{}{}
+ newGroup = append(newGroup, seq)
+ }
+ }
+ return newGroup
+}
+
+func usage() {
+ fmt.Fprintln(os.Stderr, `Usage: dupl [flags] [paths]
+
+Paths:
+ If the given path is a file, dupl will use it regardless of
+ the file extension. If it is a directory, it will recursively
+ search for *.go files in that directory.
+
+ If no path is given, dupl will recursively search for *.go
+ files in the current directory.
+
+Flags:
+ -files
+ read file names from stdin one at each line
+ -html
+ output the results as HTML, including duplicate code fragments
+ -plumbing
+ plumbing (easy-to-parse) output for consumption by scripts or tools
+ -t, -threshold size
+ minimum token sequence size as a clone (default 15)
+ -vendor
+ check files in vendor directory
+ -v, -verbose
+ explain what is being done
+
+Examples:
+ dupl -t 100
+ Search clones in the current directory of size at least
+ 100 tokens.
+ dupl $(find app/ -name '*_test.go')
+ Search for clones in tests in the app directory.
+ find app/ -name '*_test.go' |dupl -files
+ The same as above.`)
+ os.Exit(2)
+}