Upgrade depguard to fix performance issue with go modules (#698)

* Upgrade depguard to fix performance issue with go modules

* Fix linting error of unused function
This commit is contained in:
Will Dixon 2019-09-15 07:13:16 -04:00 committed by Isaev Denis
parent fc8d614b2b
commit 9161de5b7d
15 changed files with 95 additions and 189 deletions

View File

@ -48,6 +48,7 @@ linters:
enable:
- bodyclose
- deadcode
- depguard
- dupl
- errcheck
# - funlen - TODO: enable it when golangci.com will support it.
@ -79,7 +80,6 @@ linters:
# - whitespace - TODO: enable it when golangci.com will support it.
# don't enable:
# - depguard - until https://github.com/OpenPeeDeeP/depguard/issues/7 gets fixed
# - maligned,prealloc
# - gochecknoglobals

View File

@ -14,9 +14,7 @@ clean:
.PHONY: fast_build build build_race clean
# Test
# until https://github.com/OpenPeeDeeP/depguard/issues/7 fixed
test: export GO111MODULE = off
test: export GO111MODULE = on
test: export GOLANGCI_LINT_INSTALLED = true
test: build

View File

@ -907,6 +907,7 @@ linters:
enable:
- bodyclose
- deadcode
- depguard
- dupl
- errcheck
# - funlen - TODO: enable it when golangci.com will support it.
@ -938,7 +939,6 @@ linters:
# - whitespace - TODO: enable it when golangci.com will support it.
# don't enable:
# - depguard - until https://github.com/OpenPeeDeeP/depguard/issues/7 gets fixed
# - maligned,prealloc
# - gochecknoglobals

3
go.mod
View File

@ -3,13 +3,12 @@ module github.com/golangci/golangci-lint
go 1.11
require (
github.com/OpenPeeDeeP/depguard v1.0.0
github.com/OpenPeeDeeP/depguard v1.0.1
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/fatih/color v1.7.0
github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db
github.com/go-lintpack/lintpack v0.5.2
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/golang/mock v1.3.1
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a

4
go.sum
View File

@ -2,8 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OpenPeeDeeP/depguard v1.0.0 h1:k9QF73nrHT3nPLz3lu6G5s+3Hi8Je36ODr1F5gjAXXM=
github.com/OpenPeeDeeP/depguard v1.0.0/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o=
github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us=
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=

View File

@ -92,8 +92,6 @@ func NewRunner(astCache *astcache.Cache, cfg *config.Config, log logutils.Log, g
}, nil
}
func someUnusedFunc() {}
type lintRes struct {
linter *linter.Config
err error

View File

@ -10,3 +10,5 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
.idea

View File

@ -1,43 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/gobwas/glob"
packages = [
".",
"compiler",
"match",
"syntax",
"syntax/ast",
"syntax/lexer",
"util/runes",
"util/strings"
]
revision = "5ccd90ef52e1e632236f7326478d4faa74f99438"
version = "v0.2.3"
[[projects]]
name = "github.com/kisielk/gotool"
packages = [
".",
"internal/load"
]
revision = "80517062f582ea3340cd4baf70e86d539ae7d84d"
version = "v1.0.0"
[[projects]]
branch = "master"
name = "golang.org/x/tools"
packages = [
"go/ast/astutil",
"go/buildutil",
"go/loader"
]
revision = "a5b4c53f6e8bdcafa95a94671bf2d1203365858b"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "7dd6ca0cba46360ae2d416534019ea1431850a15a69336f47a1098633d08e7b4"
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -1,43 +0,0 @@
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true
ignored = ["github.com/davecgh/go-spew/spew"]
[prune]
go-tests = true
unused-packages = true
[[constraint]]
name = "github.com/kisielk/gotool"
version = "1.0.0"
[[constraint]]
branch = "master"
name = "golang.org/x/tools"
[[constraint]]
name = "github.com/gobwas/glob"
version = "0.2.3"

View File

@ -25,22 +25,22 @@ The following is an example configuration file.
```json
{
"type": "whitelist",
"packages": [
"github.com/OpenPeeDeeP/depguard"
],
"inTests": [
"github.com/stretchr/testify"
],
"includeGoRoot": true
"packages": ["github.com/OpenPeeDeeP/depguard"],
"packageErrorMessages": {
"github.com/OpenPeeDeeP/depguards": "Please use \"github.com/OpenPeeDeeP/depguard\","
},
"inTests": ["github.com/stretchr/testify"],
"includeGoStdLib": true
}
```
- `type` can be either `whitelist` or `blacklist`. This check is case insensitive.
If not specified the default is `blacklist`.
If not specified the default is `blacklist`.
- `packages` is a list of packages for the list type specified.
- `packageErrorMessages` is a mapping from packages to the error message to display
- `inTests` is a list of packages allowed/disallowed only in test files.
- Set `includeGoRoot` to true if you want to check the list against standard lib.
If not specified the default is false.
- Set `includeGoStdLib` (`includeGoRoot` for backwards compatability) to true if you want to check the list against standard lib.
If not specified the default is false.
## Gometalinter

View File

@ -1,8 +1,10 @@
package depguard
import (
"go/build"
"go/token"
"os"
"io/ioutil"
"path"
"sort"
"strings"
@ -46,8 +48,7 @@ type Depguard struct {
prefixTestPackages []string
globTestPackages []glob.Glob
rootChecker *RootChecker
cwd string
prefixRoot []string
}
// Run checks for dependencies given the program and validates them against
@ -86,18 +87,6 @@ func (dg *Depguard) Run(config *loader.Config, prog *loader.Program) ([]*Issue,
}
func (dg *Depguard) initialize(config *loader.Config, prog *loader.Program) error {
// Try and get the current working directory
dg.cwd = config.Cwd
if dg.cwd == "" {
var err error
dg.cwd, err = os.Getwd()
if err != nil {
return err
}
}
dg.rootChecker = NewRootChecker(config.Build)
// parse ordinary guarded packages
for _, pkg := range dg.Packages {
if strings.ContainsAny(pkg, "!?*[]{}") {
@ -130,6 +119,14 @@ func (dg *Depguard) initialize(config *loader.Config, prog *loader.Program) erro
// Sort the test packages so we can have a faster search in the array
sort.Strings(dg.prefixTestPackages)
if !dg.IncludeGoRoot {
var err error
dg.prefixRoot, err = listRootPrefixs(config.Build)
if err != nil {
return err
}
}
return nil
}
@ -143,14 +140,8 @@ func (dg *Depguard) createImportMap(prog *loader.Program) (map[string][]token.Po
// This will filter out GoRoot depending on the Depguard.IncludeGoRoot
for _, fileImport := range file.Imports {
fileImportPath := cleanBasicLitString(fileImport.Path.Value)
if !dg.IncludeGoRoot {
isRoot, err := dg.rootChecker.IsRoot(fileImportPath, dg.cwd)
if err != nil {
return nil, err
}
if isRoot {
continue
}
if !dg.IncludeGoRoot && dg.isRoot(fileImportPath) {
continue
}
position := prog.Fset.Position(fileImport.Pos())
positions, found := importMap[fileImportPath]
@ -167,14 +158,14 @@ func (dg *Depguard) createImportMap(prog *loader.Program) (map[string][]token.Po
return importMap, nil
}
func (dg *Depguard) pkgInList(pkg string, prefixList []string, globList []glob.Glob) bool {
if dg.pkgInPrefixList(pkg, prefixList) {
func pkgInList(pkg string, prefixList []string, globList []glob.Glob) bool {
if pkgInPrefixList(pkg, prefixList) {
return true
}
return dg.pkgInGlobList(pkg, globList)
return pkgInGlobList(pkg, globList)
}
func (dg *Depguard) pkgInPrefixList(pkg string, prefixList []string) bool {
func pkgInPrefixList(pkg string, prefixList []string) bool {
// Idx represents where in the package slice the passed in package would go
// when sorted. -1 Just means that it would be at the very front of the slice.
idx := sort.Search(len(prefixList), func(i int) bool {
@ -188,7 +179,7 @@ func (dg *Depguard) pkgInPrefixList(pkg string, prefixList []string) bool {
return strings.HasPrefix(pkg, prefixList[idx])
}
func (dg *Depguard) pkgInGlobList(pkg string, globList []glob.Glob) bool {
func pkgInGlobList(pkg string, globList []glob.Glob) bool {
for _, g := range globList {
if g.Match(pkg) {
return true
@ -201,9 +192,50 @@ func (dg *Depguard) pkgInGlobList(pkg string, globList []glob.Glob) bool {
// y | | x
// n | x |
func (dg *Depguard) flagIt(pkg string, prefixList []string, globList []glob.Glob) bool {
return dg.pkgInList(pkg, prefixList, globList) == (dg.ListType == LTBlacklist)
return pkgInList(pkg, prefixList, globList) == (dg.ListType == LTBlacklist)
}
func cleanBasicLitString(value string) string {
return strings.Trim(value, "\"\\")
}
// We can do this as all imports that are not root are either prefixed with a domain
// or prefixed with `./` or `/` to dictate it is a local file reference
func listRootPrefixs(buildCtx *build.Context) ([]string, error) {
if buildCtx == nil {
buildCtx = &build.Default
}
root := path.Join(buildCtx.GOROOT, "src")
fs, err := ioutil.ReadDir(root)
if err != nil {
return nil, err
}
var pkgPrefix []string
for _, f := range fs {
if !f.IsDir() {
continue
}
pkgPrefix = append(pkgPrefix, f.Name())
}
return pkgPrefix, nil
}
func (dg *Depguard) isRoot(importPath string) bool {
// Idx represents where in the package slice the passed in package would go
// when sorted. -1 Just means that it would be at the very front of the slice.
idx := sort.Search(len(dg.prefixRoot), func(i int) bool {
return dg.prefixRoot[i] > importPath
}) - 1
// This means that the package passed in has no way to be prefixed by anything
// in the package list as it is already smaller then everything
if idx == -1 {
return false
}
// if it is prefixed by a root prefix we need to check if it is an exact match
// or prefix with `/` as this could return false posative if the domain was
// `archive.com` for example as `archive` is a go root package.
if strings.HasPrefix(importPath, dg.prefixRoot[idx]) {
return strings.HasPrefix(importPath, dg.prefixRoot[idx]+"/") || importPath == dg.prefixRoot[idx]
}
return false
}

9
vendor/github.com/OpenPeeDeeP/depguard/go.mod generated vendored Normal file
View File

@ -0,0 +1,9 @@
module github.com/OpenPeeDeeP/depguard
go 1.13
require (
github.com/gobwas/glob v0.2.3
github.com/kisielk/gotool v1.0.0
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b
)

6
vendor/github.com/OpenPeeDeeP/depguard/go.sum generated vendored Normal file
View File

@ -0,0 +1,6 @@
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b h1:7tibmaEqrQYA+q6ri7NQjuxqSwechjtDHKq6/e85S38=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@ -1,52 +0,0 @@
package depguard
import (
"go/build"
)
// RootChecker checks if import paths point to root packages.
type RootChecker struct {
buildCtx *build.Context
cache map[string]bool
}
// NewRootChecker creates a new RootChecker instance using the build.Context
// given, or build.Default.
func NewRootChecker(buildCtx *build.Context) *RootChecker {
// Use the &build.Default if build.Context is not specified
ctx := buildCtx
if ctx == nil {
ctx = &build.Default
}
return &RootChecker{
buildCtx: ctx,
cache: make(map[string]bool, 0),
}
}
// IsRoot checks if the given import path (imported from sourceDir)
// points to a a root package. Subsequent calls with the same arguments
// are cached. This is not thread-safe.
func (rc *RootChecker) IsRoot(path, sourceDir string) (bool, error) {
key := path + ":::" + sourceDir
isRoot, ok := rc.cache[key]
if ok {
return isRoot, nil
}
isRoot, err := rc.calcIsRoot(path, sourceDir)
if err != nil {
return false, err
}
rc.cache[key] = isRoot
return isRoot, nil
}
// calcIsRoot performs the call to the build context to check if
// the import path points to a root package.
func (rc *RootChecker) calcIsRoot(path, sourceDir string) (bool, error) {
pkg, err := rc.buildCtx.Import(path, sourceDir, build.FindOnly)
if err != nil {
return false, err
}
return pkg.Goroot, nil
}

2
vendor/modules.txt vendored
View File

@ -1,6 +1,6 @@
# github.com/BurntSushi/toml v0.3.1
github.com/BurntSushi/toml
# github.com/OpenPeeDeeP/depguard v1.0.0
# github.com/OpenPeeDeeP/depguard v1.0.1
github.com/OpenPeeDeeP/depguard
# github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d
github.com/StackExchange/wmi