#45: fix no results for gocyclo
This commit is contained in:
parent
80a5ff2eff
commit
ef81b998ed
@ -1,16 +1,21 @@
|
|||||||
package astcache
|
package astcache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/tools/go/loader"
|
"golang.org/x/tools/go/loader"
|
||||||
)
|
)
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
F *ast.File
|
F *ast.File
|
||||||
Fset *token.FileSet
|
Fset *token.FileSet
|
||||||
|
Name string
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,22 +39,40 @@ func (c *Cache) prepareValidFiles() {
|
|||||||
c.s = files
|
c.s = files
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadFromProgram(prog *loader.Program) *Cache {
|
func LoadFromProgram(prog *loader.Program) (*Cache, error) {
|
||||||
c := &Cache{
|
c := &Cache{
|
||||||
m: map[string]*File{},
|
m: map[string]*File{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't get working dir: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
for _, pkg := range prog.InitialPackages() {
|
for _, pkg := range prog.InitialPackages() {
|
||||||
for _, f := range pkg.Files {
|
for _, f := range pkg.Files {
|
||||||
pos := prog.Fset.Position(0)
|
pos := prog.Fset.Position(f.Pos())
|
||||||
c.m[pos.Filename] = &File{
|
if pos.Filename == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
relPath, err := filepath.Rel(root, pos.Filename)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Warnf("Can't get relative path for %s and %s: %s",
|
||||||
|
root, pos.Filename, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
c.m[relPath] = &File{
|
||||||
F: f,
|
F: f,
|
||||||
Fset: prog.Fset,
|
Fset: prog.Fset,
|
||||||
|
Name: relPath,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.prepareValidFiles()
|
c.prepareValidFiles()
|
||||||
return c
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadFromFiles(files []string) *Cache {
|
func LoadFromFiles(files []string) *Cache {
|
||||||
@ -63,6 +86,7 @@ func LoadFromFiles(files []string) *Cache {
|
|||||||
F: f,
|
F: f,
|
||||||
Fset: fset,
|
Fset: fset,
|
||||||
err: err,
|
err: err,
|
||||||
|
Name: filePath,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,17 +12,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (e *Executor) initRoot() {
|
func (e *Executor) persistentPostRun(cmd *cobra.Command, args []string) {
|
||||||
rootCmd := &cobra.Command{
|
|
||||||
Use: "golangci-lint",
|
|
||||||
Short: "golangci-lint is a smart linters runner.",
|
|
||||||
Long: `Smart, fast linters runner. Run it in cloud for every GitHub pull request on https://golangci.com`,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
if err := cmd.Help(); err != nil {
|
|
||||||
logrus.Fatal(err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
if e.cfg.Run.PrintVersion {
|
if e.cfg.Run.PrintVersion {
|
||||||
fmt.Fprintf(printers.StdOut, "golangci-lint has version %s built from %s on %s\n", e.version, e.commit, e.date)
|
fmt.Fprintf(printers.StdOut, "golangci-lint has version %s built from %s on %s\n", e.version, e.commit, e.date)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
@ -46,8 +36,9 @@ func (e *Executor) initRoot() {
|
|||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
|
func (e *Executor) persistentPreRun(cmd *cobra.Command, args []string) {
|
||||||
if e.cfg.Run.CPUProfilePath != "" {
|
if e.cfg.Run.CPUProfilePath != "" {
|
||||||
pprof.StopCPUProfile()
|
pprof.StopCPUProfile()
|
||||||
}
|
}
|
||||||
@ -63,7 +54,20 @@ func (e *Executor) initRoot() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(e.exitCode)
|
os.Exit(e.exitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Executor) initRoot() {
|
||||||
|
rootCmd := &cobra.Command{
|
||||||
|
Use: "golangci-lint",
|
||||||
|
Short: "golangci-lint is a smart linters runner.",
|
||||||
|
Long: `Smart, fast linters runner. Run it in cloud for every GitHub pull request on https://golangci.com`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if err := cmd.Help(); err != nil {
|
||||||
|
logrus.Fatal(err)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
PersistentPreRun: e.persistentPostRun,
|
||||||
|
PersistentPostRun: e.persistentPreRun,
|
||||||
}
|
}
|
||||||
rootCmd.PersistentFlags().BoolVarP(&e.cfg.Run.IsVerbose, "verbose", "v", false, "verbose output")
|
rootCmd.PersistentFlags().BoolVarP(&e.cfg.Run.IsVerbose, "verbose", "v", false, "verbose output")
|
||||||
rootCmd.PersistentFlags().StringVar(&e.cfg.Run.CPUProfilePath, "cpu-profile-path", "", "Path to CPU profile output file")
|
rootCmd.PersistentFlags().StringVar(&e.cfg.Run.CPUProfilePath, "cpu-profile-path", "", "Path to CPU profile output file")
|
||||||
|
@ -254,7 +254,10 @@ func buildLintCtx(ctx context.Context, linters []pkg.Linter, cfg *config.Config)
|
|||||||
|
|
||||||
var astCache *astcache.Cache
|
var astCache *astcache.Cache
|
||||||
if prog != nil {
|
if prog != nil {
|
||||||
astCache = astcache.LoadFromProgram(prog)
|
astCache, err = astcache.LoadFromProgram(prog)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
astCache = astcache.LoadFromFiles(paths.Files)
|
astCache = astcache.LoadFromFiles(paths.Files)
|
||||||
}
|
}
|
||||||
|
54
pkg/commands/run_test.go
Normal file
54
pkg/commands/run_test.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golangci/golangci-lint/pkg"
|
||||||
|
"github.com/golangci/golangci-lint/pkg/astcache"
|
||||||
|
"github.com/golangci/golangci-lint/pkg/config"
|
||||||
|
"github.com/golangci/golangci-lint/pkg/fsutils"
|
||||||
|
"github.com/golangci/golangci-lint/pkg/golinters"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestASTCacheLoading(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
linters := []pkg.Linter{golinters.Errcheck{}}
|
||||||
|
|
||||||
|
inputPaths := []string{"./...", "./", "./run.go", "run.go"}
|
||||||
|
for _, inputPath := range inputPaths {
|
||||||
|
paths, err := fsutils.GetPathsForAnalysis(ctx, []string{inputPath}, true)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, paths.Files)
|
||||||
|
|
||||||
|
prog, _, err := loadWholeAppIfNeeded(ctx, linters, &config.Run{
|
||||||
|
AnalyzeTests: true,
|
||||||
|
}, paths)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
astCacheFromProg, err := astcache.LoadFromProgram(prog)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
astCacheFromFiles := astcache.LoadFromFiles(paths.Files)
|
||||||
|
|
||||||
|
filesFromProg := astCacheFromProg.GetAllValidFiles()
|
||||||
|
filesFromFiles := astCacheFromFiles.GetAllValidFiles()
|
||||||
|
if len(filesFromProg) != len(filesFromFiles) {
|
||||||
|
t.Logf("files: %s", paths.Files)
|
||||||
|
t.Logf("from prog:")
|
||||||
|
for _, f := range filesFromProg {
|
||||||
|
t.Logf("%+v", *f)
|
||||||
|
}
|
||||||
|
t.Logf("from files:")
|
||||||
|
for _, f := range filesFromFiles {
|
||||||
|
t.Logf("%+v", *f)
|
||||||
|
}
|
||||||
|
t.Fatalf("lengths differ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(filesFromProg) != len(paths.Files) {
|
||||||
|
t.Fatalf("filesFromProg differ from path.Files")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -294,9 +294,7 @@ func GetAllLintersForPreset(p string) []Linter {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEnabledLintersSet(cfg *config.Config) map[string]Linter { // nolint:gocyclo
|
func getEnabledLintersSet(lcfg *config.Linters, enabledByDefaultLinters []Linter) map[string]Linter { // nolint:gocyclo
|
||||||
lcfg := &cfg.Linters
|
|
||||||
|
|
||||||
resultLintersSet := map[string]Linter{}
|
resultLintersSet := map[string]Linter{}
|
||||||
switch {
|
switch {
|
||||||
case len(lcfg.Presets) != 0:
|
case len(lcfg.Presets) != 0:
|
||||||
@ -306,7 +304,7 @@ func getEnabledLintersSet(cfg *config.Config) map[string]Linter { // nolint:gocy
|
|||||||
case lcfg.DisableAll:
|
case lcfg.DisableAll:
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
resultLintersSet = lintersToMap(getAllEnabledByDefaultLinters())
|
resultLintersSet = lintersToMap(enabledByDefaultLinters)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --presets can only add linters to default set
|
// --presets can only add linters to default set
|
||||||
@ -332,12 +330,24 @@ func getEnabledLintersSet(cfg *config.Config) map[string]Linter { // nolint:gocy
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range lcfg.Disable {
|
for _, name := range lcfg.Disable {
|
||||||
|
if name == "megacheck" {
|
||||||
|
for _, ln := range getAllMegacheckSubLinterNames() {
|
||||||
|
delete(resultLintersSet, ln)
|
||||||
|
}
|
||||||
|
}
|
||||||
delete(resultLintersSet, name)
|
delete(resultLintersSet, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultLintersSet
|
return resultLintersSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAllMegacheckSubLinterNames() []string {
|
||||||
|
unusedName := golinters.Megacheck{UnusedEnabled: true}.Name()
|
||||||
|
gosimpleName := golinters.Megacheck{GosimpleEnabled: true}.Name()
|
||||||
|
staticcheckName := golinters.Megacheck{StaticcheckEnabled: true}.Name()
|
||||||
|
return []string{unusedName, gosimpleName, staticcheckName}
|
||||||
|
}
|
||||||
|
|
||||||
func optimizeLintersSet(linters map[string]Linter) {
|
func optimizeLintersSet(linters map[string]Linter) {
|
||||||
unusedName := golinters.Megacheck{UnusedEnabled: true}.Name()
|
unusedName := golinters.Megacheck{UnusedEnabled: true}.Name()
|
||||||
gosimpleName := golinters.Megacheck{GosimpleEnabled: true}.Name()
|
gosimpleName := golinters.Megacheck{GosimpleEnabled: true}.Name()
|
||||||
@ -375,7 +385,7 @@ func GetEnabledLinters(cfg *config.Config) ([]Linter, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resultLintersSet := getEnabledLintersSet(cfg)
|
resultLintersSet := getEnabledLintersSet(&cfg.Linters, getAllEnabledByDefaultLinters())
|
||||||
optimizeLintersSet(resultLintersSet)
|
optimizeLintersSet(resultLintersSet)
|
||||||
|
|
||||||
var resultLinters []Linter
|
var resultLinters []Linter
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -370,3 +371,48 @@ func BenchmarkWithGometalinter(b *testing.B) {
|
|||||||
compare(b, runGometalinter, runGolangciLint, bc.name, "", lc/1000)
|
compare(b, runGometalinter, runGolangciLint, bc.name, "", lc/1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetEnabledLintersSet(t *testing.T) {
|
||||||
|
type cs struct {
|
||||||
|
cfg config.Linters
|
||||||
|
name string // test case name
|
||||||
|
def []string // enabled by default linters
|
||||||
|
exp []string // alphabetically ordered enabled linter names
|
||||||
|
}
|
||||||
|
cases := []cs{
|
||||||
|
{
|
||||||
|
cfg: config.Linters{
|
||||||
|
Disable: []string{"megacheck"},
|
||||||
|
},
|
||||||
|
name: "disable all linters from megacheck",
|
||||||
|
def: getAllMegacheckSubLinterNames(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cfg: config.Linters{
|
||||||
|
Disable: []string{"staticcheck"},
|
||||||
|
},
|
||||||
|
name: "disable only staticcheck",
|
||||||
|
def: getAllMegacheckSubLinterNames(),
|
||||||
|
exp: []string{"gosimple", "unused"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
defaultLinters := []Linter{}
|
||||||
|
for _, ln := range c.def {
|
||||||
|
defaultLinters = append(defaultLinters, getLinterByName(ln))
|
||||||
|
}
|
||||||
|
els := getEnabledLintersSet(&c.cfg, defaultLinters)
|
||||||
|
var enabledLinters []string
|
||||||
|
for ln := range els {
|
||||||
|
enabledLinters = append(enabledLinters, ln)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(enabledLinters)
|
||||||
|
sort.Strings(c.exp)
|
||||||
|
|
||||||
|
assert.Equal(t, c.exp, enabledLinters)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user