github.com/nozzle/golangci-lint@v1.49.0-nz3/pkg/golinters/dupl.go (about) 1 package golinters 2 3 import ( 4 "fmt" 5 "go/token" 6 "sync" 7 8 duplAPI "github.com/golangci/dupl" 9 "github.com/pkg/errors" 10 "golang.org/x/tools/go/analysis" 11 12 "github.com/golangci/golangci-lint/pkg/config" 13 "github.com/golangci/golangci-lint/pkg/fsutils" 14 "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 15 "github.com/golangci/golangci-lint/pkg/lint/linter" 16 "github.com/golangci/golangci-lint/pkg/result" 17 ) 18 19 const duplName = "dupl" 20 21 //nolint:dupl 22 func NewDupl(settings *config.DuplSettings) *goanalysis.Linter { 23 var mu sync.Mutex 24 var resIssues []goanalysis.Issue 25 26 analyzer := &analysis.Analyzer{ 27 Name: duplName, 28 Doc: goanalysis.TheOnlyanalyzerDoc, 29 Run: func(pass *analysis.Pass) (interface{}, error) { 30 issues, err := runDupl(pass, settings) 31 if err != nil { 32 return nil, err 33 } 34 35 if len(issues) == 0 { 36 return nil, nil 37 } 38 39 mu.Lock() 40 resIssues = append(resIssues, issues...) 41 mu.Unlock() 42 43 return nil, nil 44 }, 45 } 46 47 return goanalysis.NewLinter( 48 duplName, 49 "Tool for code clone detection", 50 []*analysis.Analyzer{analyzer}, 51 nil, 52 ).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { 53 return resIssues 54 }).WithLoadMode(goanalysis.LoadModeSyntax) 55 } 56 57 func runDupl(pass *analysis.Pass, settings *config.DuplSettings) ([]goanalysis.Issue, error) { 58 fileNames := getFileNames(pass) 59 60 issues, err := duplAPI.Run(fileNames, settings.Threshold) 61 if err != nil { 62 return nil, err 63 } 64 65 if len(issues) == 0 { 66 return nil, nil 67 } 68 69 res := make([]goanalysis.Issue, 0, len(issues)) 70 71 for _, i := range issues { 72 toFilename, err := fsutils.ShortestRelPath(i.To.Filename(), "") 73 if err != nil { 74 return nil, errors.Wrapf(err, "failed to get shortest rel path for %q", i.To.Filename()) 75 } 76 77 dupl := fmt.Sprintf("%s:%d-%d", toFilename, i.To.LineStart(), i.To.LineEnd()) 78 text := fmt.Sprintf("%d-%d lines are duplicate of %s", 79 i.From.LineStart(), i.From.LineEnd(), 80 formatCode(dupl, nil)) 81 82 res = append(res, goanalysis.NewIssue(&result.Issue{ 83 Pos: token.Position{ 84 Filename: i.From.Filename(), 85 Line: i.From.LineStart(), 86 }, 87 LineRange: &result.Range{ 88 From: i.From.LineStart(), 89 To: i.From.LineEnd(), 90 }, 91 Text: text, 92 FromLinter: duplName, 93 }, pass)) 94 } 95 96 return res, nil 97 }