This commit is contained in:
parent
3814b8a504
commit
018dd8164c
@ -28,6 +28,7 @@ pipeline:
|
||||
# - make got-swag # Commented out until we figured out how to get this working on drone
|
||||
- make ineffassign-check
|
||||
- make misspell-check
|
||||
- make goconst-check
|
||||
- make build
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
@ -124,3 +124,11 @@ Sorry for some of them being in German, I'll tranlate them at some point.
|
||||
* [ ] Mgl., dass die Instanz geschlossen ist, also sich keiner registrieren kann, und man sich einloggen muss
|
||||
* [ ] mgl. zum Emailmaskieren haben (in den Nutzereinstellungen, wenn man seine Email nicht an alle Welt rausposaunen will)
|
||||
* [ ] Mgl. zum Accountlöschen haben (so richtig krass mit emailverifiezierung und dass alle Privaten Listen gelöscht werden und man alle geteilten entweder wem übertragen muss oder auf privat stellen)
|
||||
|
||||
### Linters
|
||||
|
||||
* [x] goconst
|
||||
* [ ] Gosimple -> waiting for mod
|
||||
* [ ] Staticcheck -> waiting for mod
|
||||
* [ ] unused -> waiting for mod
|
||||
* [ ] gosec -> waiting for mod
|
36
Makefile
36
Makefile
@ -187,3 +187,39 @@ gocyclo-check:
|
||||
go install $(GOFLAGS) github.com/fzipp/gocyclo; \
|
||||
fi
|
||||
for S in $(GOFILES); do gocyclo -over 14 $$S || exit 1; done;
|
||||
|
||||
.PHONY: gosimple-check
|
||||
gosimple-check:
|
||||
@hash gosimple > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
go get honnef.co/go/tools/cmd/gosimple; \
|
||||
fi
|
||||
for S in $(PACKAGES); do gosimple $$S || exit 1; done;
|
||||
|
||||
.PHONY: static-check
|
||||
static-check:
|
||||
@hash gocyclo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
go get honnef.co/go/tools/cmd/staticcheck; \
|
||||
fi
|
||||
staticcheck;
|
||||
|
||||
.PHONY: unused-check
|
||||
unused-check:
|
||||
@hash unused > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
go get honnef.co/go/tools/cmd/unused; \
|
||||
fi
|
||||
unused;
|
||||
|
||||
.PHONY: gosec-check
|
||||
gosec-check:
|
||||
@hash ./bin/gosec > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s 1.2.0; \
|
||||
fi
|
||||
for S in $(PACKAGES); do ./bin/gosec $$S || exit 1; done;
|
||||
|
||||
.PHONY: goconst-check
|
||||
goconst-check:
|
||||
@hash goconst > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
go get github.com/jgautheron/goconst/cmd/goconst; \
|
||||
fi
|
||||
for S in $(PACKAGES); do goconst $$S || exit 1; done;
|
||||
|
||||
|
4
go.mod
4
go.mod
@ -23,7 +23,6 @@ require (
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc
|
||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf
|
||||
github.com/client9/misspell v0.3.4
|
||||
github.com/cweill/gotests v1.5.2 // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/fzipp/gocyclo v0.0.0-20150627053110-6acd4345c835
|
||||
github.com/garyburd/redigo v1.6.0 // indirect
|
||||
@ -39,7 +38,9 @@ require (
|
||||
github.com/go-xorm/xorm-redis-cache v0.0.0-20180727005610-859b313566b2
|
||||
github.com/gordonklaus/ineffassign v0.0.0-20180909121442-1003c8bd00dc
|
||||
github.com/imdario/mergo v0.3.6
|
||||
github.com/jgautheron/goconst v0.0.0-20170703170152-9740945f5dcb
|
||||
github.com/karalabe/xgo v0.0.0-20181007145344-72da7d1d3970
|
||||
github.com/kisielk/gotool v1.0.0 // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/labstack/echo v3.3.5+incompatible
|
||||
github.com/labstack/gommon v0.2.8
|
||||
@ -68,4 +69,5 @@ require (
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/testfixtures.v2 v2.5.3
|
||||
gopkg.in/yaml.v2 v2.2.2 // indirect
|
||||
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3
|
||||
)
|
||||
|
11
go.sum
11
go.sum
@ -18,7 +18,6 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
||||
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cweill/gotests v1.5.2 h1:kKqmKmS2wCV3tuLnfpbiuN8OlkosQZTpCfiqmiuNAsA=
|
||||
github.com/cweill/gotests v1.5.2/go.mod h1:XZYOJkGVkCRoymaIzmp9Wyi3rUgfA3oOnkuljYrjFV8=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f h1:WH0w/R4Yoey+04HhFxqZ6VX6I0d7RMyw5aXQ9UTvQPs=
|
||||
@ -68,10 +67,14 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/jgautheron/goconst v0.0.0-20170703170152-9740945f5dcb h1:D5s1HIu80AcMGcqmk7fNIVptmAubVHHaj3v5Upex6Zs=
|
||||
github.com/jgautheron/goconst v0.0.0-20170703170152-9740945f5dcb/go.mod h1:82TxjOpWQiPmywlbIaB2ZkqJoSYJdLGPgAJDvM3PbKc=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/karalabe/xgo v0.0.0-20181007145344-72da7d1d3970 h1:0+1ZURVRim6FxA/jhWhJklsgoWc69q1sxlIu2Ztnhy0=
|
||||
github.com/karalabe/xgo v0.0.0-20181007145344-72da7d1d3970/go.mod h1:iYGcTYIPUvEWhFo6aKUuLchs+AV4ssYdyuBbQJZGcBk=
|
||||
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=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@ -141,10 +144,6 @@ github.com/swaggo/files v0.0.0-20180215091130-49c8a91ea3fa h1:194s4modF+3X3POBfG
|
||||
github.com/swaggo/files v0.0.0-20180215091130-49c8a91ea3fa/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
|
||||
github.com/swaggo/gin-swagger v1.0.0 h1:k6Nn1jV49u+SNIWt7kejQS/iENZKZVMCNQrKOYatNF8=
|
||||
github.com/swaggo/gin-swagger v1.0.0/go.mod h1:Mt37wE46iUaTAOv+HSnHbJYssKGqbS25X19lNF4YpBo=
|
||||
github.com/swaggo/swag v1.4.0 h1:exX5ES4CdJWCCKmVPE+FAIN66cnHeMHU3i2SCMibBZc=
|
||||
github.com/swaggo/swag v1.4.0/go.mod h1:hog2WgeMOrQ/LvQ+o1YGTeT+vWVrbi0SiIslBtxKTyM=
|
||||
github.com/swaggo/swag v1.4.1-0.20181129020348-1c8533a91397 h1:xhlin3d0mSsxQlwxS+fHILT6PgG4Cmc2OZgzZL2bemI=
|
||||
github.com/swaggo/swag v1.4.1-0.20181129020348-1c8533a91397/go.mod h1:hog2WgeMOrQ/LvQ+o1YGTeT+vWVrbi0SiIslBtxKTyM=
|
||||
github.com/swaggo/swag v1.4.1-0.20181210033626-0e12fd5eb026 h1:XAOjF3QgjDUkVrPMO4rYvNptSHQgUlHwQsEdJOTxHQ8=
|
||||
github.com/swaggo/swag v1.4.1-0.20181210033626-0e12fd5eb026/go.mod h1:hog2WgeMOrQ/LvQ+o1YGTeT+vWVrbi0SiIslBtxKTyM=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
@ -202,3 +201,5 @@ gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3 h1:LyX67rVB0kBUFoROrQfzKwdrYLH1cRzHibxdJW85J1c=
|
||||
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
5
tools.go
5
tools.go
@ -29,4 +29,9 @@ import (
|
||||
_ "github.com/swaggo/echo-swagger"
|
||||
_ "github.com/swaggo/swag/cmd/swag"
|
||||
_ "golang.org/x/lint/golint"
|
||||
|
||||
_ "github.com/jgautheron/goconst/cmd/goconst"
|
||||
_ "honnef.co/go/tools/cmd/gosimple"
|
||||
_ "honnef.co/go/tools/cmd/staticcheck"
|
||||
_ "honnef.co/go/tools/cmd/unused"
|
||||
)
|
||||
|
21
vendor/github.com/jgautheron/goconst/LICENSE
generated
vendored
Normal file
21
vendor/github.com/jgautheron/goconst/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Jonathan Gautheron
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
49
vendor/github.com/jgautheron/goconst/README.md
generated
vendored
Normal file
49
vendor/github.com/jgautheron/goconst/README.md
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
# goconst
|
||||
|
||||
Find repeated strings that could be replaced by a constant.
|
||||
|
||||
### Motivation
|
||||
|
||||
There are obvious benefits to using constants instead of repeating strings, mostly to ease maintenance. Cannot argue against changing a single constant versus many strings.
|
||||
|
||||
While this could be considered a beginner mistake, across time, multiple packages and large codebases, some repetition could have slipped in.
|
||||
|
||||
### Get Started
|
||||
|
||||
$ go get github.com/jgautheron/goconst/cmd/goconst
|
||||
$ goconst ./...
|
||||
|
||||
### Usage
|
||||
|
||||
```
|
||||
Usage:
|
||||
|
||||
goconst ARGS <directory>
|
||||
|
||||
Flags:
|
||||
|
||||
-ignore exclude files matching the given regular expression
|
||||
-ignore-tests exclude tests from the search (default: true)
|
||||
-min-occurrences report from how many occurrences (default: 2)
|
||||
-min-length only report strings with the minimum given length (default: 3)
|
||||
-match-constant look for existing constants matching the values
|
||||
-numbers search also for duplicated numbers
|
||||
-min minimum value, only works with -numbers
|
||||
-max maximum value, only works with -numbers
|
||||
-output output formatting (text or json)
|
||||
|
||||
Examples:
|
||||
|
||||
goconst ./...
|
||||
goconst -ignore "yacc|\.pb\." $GOPATH/src/github.com/cockroachdb/cockroach/...
|
||||
goconst -min-occurrences 3 -output json $GOPATH/src/github.com/cockroachdb/cockroach
|
||||
goconst -numbers -min 60 -max 512 .
|
||||
```
|
||||
|
||||
### Other static analysis tools
|
||||
|
||||
- [gogetimports](https://github.com/jgautheron/gogetimports): Get a JSON-formatted list of imports.
|
||||
- [usedexports](https://github.com/jgautheron/usedexports): Find exported variables that could be unexported.
|
||||
|
||||
### License
|
||||
MIT
|
166
vendor/github.com/jgautheron/goconst/cmd/goconst/main.go
generated
vendored
Normal file
166
vendor/github.com/jgautheron/goconst/cmd/goconst/main.go
generated
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jgautheron/goconst"
|
||||
)
|
||||
|
||||
const usageDoc = `goconst: find repeated strings that could be replaced by a constant
|
||||
|
||||
Usage:
|
||||
|
||||
goconst ARGS <directory> [<directory>...]
|
||||
|
||||
Flags:
|
||||
|
||||
-ignore exclude files matching the given regular expression
|
||||
-ignore-tests exclude tests from the search (default: true)
|
||||
-min-occurrences report from how many occurrences (default: 2)
|
||||
-min-length only report strings with the minimum given length (default: 3)
|
||||
-match-constant look for existing constants matching the strings
|
||||
-numbers search also for duplicated numbers
|
||||
-min minimum value, only works with -numbers
|
||||
-max maximum value, only works with -numbers
|
||||
-output output formatting (text or json)
|
||||
|
||||
Examples:
|
||||
|
||||
goconst ./...
|
||||
goconst -ignore "yacc|\.pb\." $GOPATH/src/github.com/cockroachdb/cockroach/...
|
||||
goconst -min-occurrences 3 -output json $GOPATH/src/github.com/cockroachdb/cockroach
|
||||
goconst -numbers -min 60 -max 512 .
|
||||
`
|
||||
|
||||
var (
|
||||
flagIgnore = flag.String("ignore", "", "ignore files matching the given regular expression")
|
||||
flagIgnoreTests = flag.Bool("ignore-tests", true, "exclude tests from the search")
|
||||
flagMinOccurrences = flag.Int("min-occurrences", 2, "report from how many occurrences")
|
||||
flagMinLength = flag.Int("min-length", 3, "only report strings with the minimum given length")
|
||||
flagMatchConstant = flag.Bool("match-constant", false, "look for existing constants matching the strings")
|
||||
flagNumbers = flag.Bool("numbers", false, "search also for duplicated numbers")
|
||||
flagMin = flag.Int("min", 0, "minimum value, only works with -numbers")
|
||||
flagMax = flag.Int("max", 0, "maximum value, only works with -numbers")
|
||||
flagOutput = flag.String("output", "text", "output formatting")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
usage(os.Stderr)
|
||||
}
|
||||
flag.Parse()
|
||||
log.SetPrefix("goconst: ")
|
||||
|
||||
args := flag.Args()
|
||||
if len(args) < 1 {
|
||||
usage(os.Stderr)
|
||||
os.Exit(1)
|
||||
}
|
||||
for _, path := range args {
|
||||
if err := run(path); err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func run(path string) error {
|
||||
gco := goconst.New(
|
||||
path,
|
||||
*flagIgnore,
|
||||
*flagIgnoreTests,
|
||||
*flagMatchConstant,
|
||||
*flagNumbers,
|
||||
*flagMinLength,
|
||||
)
|
||||
strs, consts, err := gco.ParseTree()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return printOutput(strs, consts, *flagOutput, *flagMinOccurrences, *flagMin, *flagMax)
|
||||
}
|
||||
|
||||
func usage(out io.Writer) {
|
||||
fmt.Fprintf(out, usageDoc)
|
||||
}
|
||||
|
||||
func printOutput(strs goconst.Strings, consts goconst.Constants, output string, minOccurrences, min, max int) error {
|
||||
for str, item := range strs {
|
||||
// Filter out items whose occurrences don't match the min value
|
||||
if len(item) < minOccurrences {
|
||||
delete(strs, str)
|
||||
}
|
||||
|
||||
// If the value is a number
|
||||
if i, err := strconv.Atoi(str); err == nil {
|
||||
if min != 0 && i < min {
|
||||
delete(strs, str)
|
||||
}
|
||||
if max != 0 && i > max {
|
||||
delete(strs, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch output {
|
||||
case "json":
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
err := enc.Encode(struct {
|
||||
Strings goconst.Strings `json:"strings,omitEmpty"`
|
||||
Constants goconst.Constants `json:"constants,omitEmpty"`
|
||||
}{
|
||||
strs, consts,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case "text":
|
||||
for str, item := range strs {
|
||||
for _, xpos := range item {
|
||||
fmt.Printf(
|
||||
`%s:%d:%d:%d other occurrence(s) of "%s" found in: %s`,
|
||||
xpos.Filename,
|
||||
xpos.Line,
|
||||
xpos.Column,
|
||||
len(item)-1,
|
||||
str,
|
||||
occurrences(item, xpos),
|
||||
)
|
||||
fmt.Print("\n")
|
||||
}
|
||||
|
||||
if len(consts) == 0 {
|
||||
continue
|
||||
}
|
||||
if cst, ok := consts[str]; ok {
|
||||
// const should be in the same package and exported
|
||||
fmt.Printf(`A matching constant has been found for "%s": %s`, str, cst.Name)
|
||||
fmt.Printf("\n\t%s\n", cst.String())
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf(`Unsupported output format: %s`, output)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func occurrences(item []goconst.ExtendedPos, current goconst.ExtendedPos) string {
|
||||
occurrences := []string{}
|
||||
for _, xpos := range item {
|
||||
if xpos == current {
|
||||
continue
|
||||
}
|
||||
occurrences = append(occurrences, fmt.Sprintf(
|
||||
"%s:%d:%d", xpos.Filename, xpos.Line, xpos.Column,
|
||||
))
|
||||
}
|
||||
return strings.Join(occurrences, " ")
|
||||
}
|
136
vendor/github.com/jgautheron/goconst/parser.go
generated
vendored
Normal file
136
vendor/github.com/jgautheron/goconst/parser.go
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
// Package goconst finds repeated strings that could be replaced by a constant.
|
||||
//
|
||||
// There are obvious benefits to using constants instead of repeating strings,
|
||||
// mostly to ease maintenance. Cannot argue against changing a single constant versus many strings.
|
||||
// While this could be considered a beginner mistake, across time,
|
||||
// multiple packages and large codebases, some repetition could have slipped in.
|
||||
package goconst
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
testSuffix = "_test.go"
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
// Meant to be passed via New()
|
||||
path, ignore string
|
||||
ignoreTests, matchConstant bool
|
||||
minLength int
|
||||
|
||||
supportedTokens []token.Token
|
||||
|
||||
// Internals
|
||||
strs Strings
|
||||
consts Constants
|
||||
}
|
||||
|
||||
// New creates a new instance of the parser.
|
||||
// This is your entry point if you'd like to use goconst as an API.
|
||||
func New(path, ignore string, ignoreTests, matchConstant, numbers bool, minLength int) *Parser {
|
||||
supportedTokens := []token.Token{token.STRING}
|
||||
if numbers {
|
||||
supportedTokens = append(supportedTokens, token.INT, token.FLOAT)
|
||||
}
|
||||
|
||||
return &Parser{
|
||||
path: path,
|
||||
ignore: ignore,
|
||||
ignoreTests: ignoreTests,
|
||||
matchConstant: matchConstant,
|
||||
minLength: minLength,
|
||||
supportedTokens: supportedTokens,
|
||||
|
||||
// Initialize the maps
|
||||
strs: Strings{},
|
||||
consts: Constants{},
|
||||
}
|
||||
}
|
||||
|
||||
// ParseTree will search the given path for occurrences that could be moved into constants.
|
||||
// If "..." is appended, the search will be recursive.
|
||||
func (p *Parser) ParseTree() (Strings, Constants, error) {
|
||||
pathLen := len(p.path)
|
||||
// Parse recursively the given path if the recursive notation is found
|
||||
if pathLen >= 5 && p.path[pathLen-3:] == "..." {
|
||||
filepath.Walk(p.path[:pathLen-3], func(path string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
// resume walking
|
||||
return nil
|
||||
}
|
||||
|
||||
if f.IsDir() {
|
||||
p.parseDir(path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
} else {
|
||||
p.parseDir(p.path)
|
||||
}
|
||||
return p.strs, p.consts, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseDir(dir string) error {
|
||||
fset := token.NewFileSet()
|
||||
pkgs, err := parser.ParseDir(fset, dir, func(info os.FileInfo) bool {
|
||||
valid, name := true, info.Name()
|
||||
|
||||
if p.ignoreTests {
|
||||
if strings.HasSuffix(name, testSuffix) {
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
|
||||
if len(p.ignore) != 0 {
|
||||
match, err := regexp.MatchString(p.ignore, dir+name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return true
|
||||
}
|
||||
if match {
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
|
||||
return valid
|
||||
}, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, pkg := range pkgs {
|
||||
for fn, f := range pkg.Files {
|
||||
ast.Walk(&treeVisitor{
|
||||
fileSet: fset,
|
||||
packageName: pkg.Name,
|
||||
fileName: fn,
|
||||
p: p,
|
||||
}, f)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Strings map[string][]ExtendedPos
|
||||
type Constants map[string]ConstType
|
||||
|
||||
type ConstType struct {
|
||||
token.Position
|
||||
Name, packageName string
|
||||
}
|
||||
|
||||
type ExtendedPos struct {
|
||||
token.Position
|
||||
packageName string
|
||||
}
|
143
vendor/github.com/jgautheron/goconst/visitor.go
generated
vendored
Normal file
143
vendor/github.com/jgautheron/goconst/visitor.go
generated
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
package goconst
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// treeVisitor carries the package name and file name
|
||||
// for passing it to the imports map, and the fileSet for
|
||||
// retrieving the token.Position.
|
||||
type treeVisitor struct {
|
||||
p *Parser
|
||||
fileSet *token.FileSet
|
||||
packageName, fileName string
|
||||
}
|
||||
|
||||
// Visit browses the AST tree for strings that could be potentially
|
||||
// replaced by constants.
|
||||
// A map of existing constants is built as well (-match-constant).
|
||||
func (v *treeVisitor) Visit(node ast.Node) ast.Visitor {
|
||||
if node == nil {
|
||||
return v
|
||||
}
|
||||
|
||||
// A single case with "ast.BasicLit" would be much easier
|
||||
// but then we wouldn't be able to tell in which context
|
||||
// the string is defined (could be a constant definition).
|
||||
switch t := node.(type) {
|
||||
// Scan for constants in an attempt to match strings with existing constants
|
||||
case *ast.GenDecl:
|
||||
if !v.p.matchConstant {
|
||||
return v
|
||||
}
|
||||
if t.Tok != token.CONST {
|
||||
return v
|
||||
}
|
||||
|
||||
for _, spec := range t.Specs {
|
||||
val := spec.(*ast.ValueSpec)
|
||||
for i, str := range val.Values {
|
||||
lit, ok := str.(*ast.BasicLit)
|
||||
if !ok || !v.isSupported(lit.Kind) {
|
||||
continue
|
||||
}
|
||||
|
||||
v.addConst(val.Names[i].Name, lit.Value, val.Names[i].Pos())
|
||||
}
|
||||
}
|
||||
|
||||
// foo := "moo"
|
||||
case *ast.AssignStmt:
|
||||
for _, rhs := range t.Rhs {
|
||||
lit, ok := rhs.(*ast.BasicLit)
|
||||
if !ok || !v.isSupported(lit.Kind) {
|
||||
continue
|
||||
}
|
||||
|
||||
v.addString(lit.Value, rhs.(*ast.BasicLit).Pos())
|
||||
}
|
||||
|
||||
// if foo == "moo"
|
||||
case *ast.BinaryExpr:
|
||||
if t.Op != token.EQL && t.Op != token.NEQ {
|
||||
return v
|
||||
}
|
||||
|
||||
var lit *ast.BasicLit
|
||||
var ok bool
|
||||
|
||||
lit, ok = t.X.(*ast.BasicLit)
|
||||
if ok && v.isSupported(lit.Kind) {
|
||||
v.addString(lit.Value, lit.Pos())
|
||||
}
|
||||
|
||||
lit, ok = t.Y.(*ast.BasicLit)
|
||||
if ok && v.isSupported(lit.Kind) {
|
||||
v.addString(lit.Value, lit.Pos())
|
||||
}
|
||||
|
||||
// case "foo":
|
||||
case *ast.CaseClause:
|
||||
for _, item := range t.List {
|
||||
lit, ok := item.(*ast.BasicLit)
|
||||
if ok && v.isSupported(lit.Kind) {
|
||||
v.addString(lit.Value, lit.Pos())
|
||||
}
|
||||
}
|
||||
|
||||
// return "boo"
|
||||
case *ast.ReturnStmt:
|
||||
for _, item := range t.Results {
|
||||
lit, ok := item.(*ast.BasicLit)
|
||||
if ok && v.isSupported(lit.Kind) {
|
||||
v.addString(lit.Value, lit.Pos())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
// Ignore empty strings
|
||||
if len(str) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if len(str) < v.p.minLength {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := v.p.strs[str]
|
||||
if !ok {
|
||||
v.p.strs[str] = make([]ExtendedPos, 0)
|
||||
}
|
||||
v.p.strs[str] = append(v.p.strs[str], ExtendedPos{
|
||||
packageName: v.packageName,
|
||||
Position: v.fileSet.Position(pos),
|
||||
})
|
||||
}
|
||||
|
||||
// addConst adds a const in the map along with its position in the tree.
|
||||
func (v *treeVisitor) addConst(name string, val string, pos token.Pos) {
|
||||
val = strings.Replace(val, `"`, "", 2)
|
||||
v.p.consts[val] = ConstType{
|
||||
Name: name,
|
||||
packageName: v.packageName,
|
||||
Position: v.fileSet.Position(pos),
|
||||
}
|
||||
}
|
||||
|
||||
func (v *treeVisitor) isSupported(tk token.Token) bool {
|
||||
for _, s := range v.p.supportedTokens {
|
||||
if tk == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
23
vendor/github.com/kisielk/gotool/.travis.yml
generated
vendored
Normal file
23
vendor/github.com/kisielk/gotool/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go:
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.7
|
||||
- 1.8
|
||||
- 1.9
|
||||
- master
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: master
|
||||
fast_finish: true
|
||||
install:
|
||||
- # Skip.
|
||||
script:
|
||||
- go get -t -v ./...
|
||||
- diff -u <(echo -n) <(gofmt -d .)
|
||||
- go tool vet .
|
||||
- go test -v -race ./...
|
32
vendor/github.com/kisielk/gotool/LEGAL
generated
vendored
Normal file
32
vendor/github.com/kisielk/gotool/LEGAL
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
All the files in this distribution are covered under either the MIT
|
||||
license (see the file LICENSE) except some files mentioned below.
|
||||
|
||||
match.go, match_test.go:
|
||||
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
20
vendor/github.com/kisielk/gotool/LICENSE
generated
vendored
Normal file
20
vendor/github.com/kisielk/gotool/LICENSE
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2013 Kamil Kisiel <kamil@kamilkisiel.net>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
6
vendor/github.com/kisielk/gotool/README.md
generated
vendored
Normal file
6
vendor/github.com/kisielk/gotool/README.md
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
gotool
|
||||
======
|
||||
[![GoDoc](https://godoc.org/github.com/kisielk/gotool?status.svg)](https://godoc.org/github.com/kisielk/gotool)
|
||||
[![Build Status](https://travis-ci.org/kisielk/gotool.svg?branch=master)](https://travis-ci.org/kisielk/gotool)
|
||||
|
||||
Package gotool contains utility functions used to implement the standard "cmd/go" tool, provided as a convenience to developers who want to write tools with similar semantics.
|
1
vendor/github.com/kisielk/gotool/go.mod
generated
vendored
Normal file
1
vendor/github.com/kisielk/gotool/go.mod
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module "github.com/kisielk/gotool"
|
15
vendor/github.com/kisielk/gotool/go13.go
generated
vendored
Normal file
15
vendor/github.com/kisielk/gotool/go13.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
// +build !go1.4
|
||||
|
||||
package gotool
|
||||
|
||||
import (
|
||||
"go/build"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var gorootSrc = filepath.Join(runtime.GOROOT(), "src", "pkg")
|
||||
|
||||
func shouldIgnoreImport(p *build.Package) bool {
|
||||
return true
|
||||
}
|
15
vendor/github.com/kisielk/gotool/go14-15.go
generated
vendored
Normal file
15
vendor/github.com/kisielk/gotool/go14-15.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
// +build go1.4,!go1.6
|
||||
|
||||
package gotool
|
||||
|
||||
import (
|
||||
"go/build"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var gorootSrc = filepath.Join(runtime.GOROOT(), "src")
|
||||
|
||||
func shouldIgnoreImport(p *build.Package) bool {
|
||||
return true
|
||||
}
|
15
vendor/github.com/kisielk/gotool/go16-18.go
generated
vendored
Normal file
15
vendor/github.com/kisielk/gotool/go16-18.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
// +build go1.6,!go1.9
|
||||
|
||||
package gotool
|
||||
|
||||
import (
|
||||
"go/build"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var gorootSrc = filepath.Join(runtime.GOROOT(), "src")
|
||||
|
||||
func shouldIgnoreImport(p *build.Package) bool {
|
||||
return p == nil || len(p.InvalidGoFiles) == 0
|
||||
}
|
27
vendor/github.com/kisielk/gotool/internal/load/path.go
generated
vendored
Normal file
27
vendor/github.com/kisielk/gotool/internal/load/path.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.9
|
||||
|
||||
package load
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// hasPathPrefix reports whether the path s begins with the
|
||||
// elements in prefix.
|
||||
func hasPathPrefix(s, prefix string) bool {
|
||||
switch {
|
||||
default:
|
||||
return false
|
||||
case len(s) == len(prefix):
|
||||
return s == prefix
|
||||
case len(s) > len(prefix):
|
||||
if prefix != "" && prefix[len(prefix)-1] == '/' {
|
||||
return strings.HasPrefix(s, prefix)
|
||||
}
|
||||
return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
|
||||
}
|
||||
}
|
25
vendor/github.com/kisielk/gotool/internal/load/pkg.go
generated
vendored
Normal file
25
vendor/github.com/kisielk/gotool/internal/load/pkg.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.9
|
||||
|
||||
// Package load loads packages.
|
||||
package load
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// isStandardImportPath reports whether $GOROOT/src/path should be considered
|
||||
// part of the standard distribution. For historical reasons we allow people to add
|
||||
// their own code to $GOROOT instead of using $GOPATH, but we assume that
|
||||
// code will start with a domain name (dot in the first element).
|
||||
func isStandardImportPath(path string) bool {
|
||||
i := strings.Index(path, "/")
|
||||
if i < 0 {
|
||||
i = len(path)
|
||||
}
|
||||
elem := path[:i]
|
||||
return !strings.Contains(elem, ".")
|
||||
}
|
354
vendor/github.com/kisielk/gotool/internal/load/search.go
generated
vendored
Normal file
354
vendor/github.com/kisielk/gotool/internal/load/search.go
generated
vendored
Normal file
@ -0,0 +1,354 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.9
|
||||
|
||||
package load
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/build"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Context specifies values for operation of ImportPaths that would
|
||||
// otherwise come from cmd/go/internal/cfg package.
|
||||
//
|
||||
// This is a construct added for gotool purposes and doesn't have
|
||||
// an equivalent upstream in cmd/go.
|
||||
type Context struct {
|
||||
// BuildContext is the build context to use.
|
||||
BuildContext build.Context
|
||||
|
||||
// GOROOTsrc is the location of the src directory in GOROOT.
|
||||
// At this time, it's used only in MatchPackages to skip
|
||||
// GOOROOT/src entry from BuildContext.SrcDirs output.
|
||||
GOROOTsrc string
|
||||
}
|
||||
|
||||
// allPackages returns all the packages that can be found
|
||||
// under the $GOPATH directories and $GOROOT matching pattern.
|
||||
// The pattern is either "all" (all packages), "std" (standard packages),
|
||||
// "cmd" (standard commands), or a path including "...".
|
||||
func (c *Context) allPackages(pattern string) []string {
|
||||
pkgs := c.MatchPackages(pattern)
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// allPackagesInFS is like allPackages but is passed a pattern
|
||||
// beginning ./ or ../, meaning it should scan the tree rooted
|
||||
// at the given directory. There are ... in the pattern too.
|
||||
func (c *Context) allPackagesInFS(pattern string) []string {
|
||||
pkgs := c.MatchPackagesInFS(pattern)
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// MatchPackages returns a list of package paths matching pattern
|
||||
// (see go help packages for pattern syntax).
|
||||
func (c *Context) MatchPackages(pattern string) []string {
|
||||
match := func(string) bool { return true }
|
||||
treeCanMatch := func(string) bool { return true }
|
||||
if !IsMetaPackage(pattern) {
|
||||
match = matchPattern(pattern)
|
||||
treeCanMatch = treeCanMatchPattern(pattern)
|
||||
}
|
||||
|
||||
have := map[string]bool{
|
||||
"builtin": true, // ignore pseudo-package that exists only for documentation
|
||||
}
|
||||
if !c.BuildContext.CgoEnabled {
|
||||
have["runtime/cgo"] = true // ignore during walk
|
||||
}
|
||||
var pkgs []string
|
||||
|
||||
for _, src := range c.BuildContext.SrcDirs() {
|
||||
if (pattern == "std" || pattern == "cmd") && src != c.GOROOTsrc {
|
||||
continue
|
||||
}
|
||||
src = filepath.Clean(src) + string(filepath.Separator)
|
||||
root := src
|
||||
if pattern == "cmd" {
|
||||
root += "cmd" + string(filepath.Separator)
|
||||
}
|
||||
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || path == src {
|
||||
return nil
|
||||
}
|
||||
|
||||
want := true
|
||||
// Avoid .foo, _foo, and testdata directory trees.
|
||||
_, elem := filepath.Split(path)
|
||||
if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
|
||||
want = false
|
||||
}
|
||||
|
||||
name := filepath.ToSlash(path[len(src):])
|
||||
if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") {
|
||||
// The name "std" is only the standard library.
|
||||
// If the name is cmd, it's the root of the command tree.
|
||||
want = false
|
||||
}
|
||||
if !treeCanMatch(name) {
|
||||
want = false
|
||||
}
|
||||
|
||||
if !fi.IsDir() {
|
||||
if fi.Mode()&os.ModeSymlink != 0 && want {
|
||||
if target, err := os.Stat(path); err == nil && target.IsDir() {
|
||||
fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !want {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
if have[name] {
|
||||
return nil
|
||||
}
|
||||
have[name] = true
|
||||
if !match(name) {
|
||||
return nil
|
||||
}
|
||||
pkg, err := c.BuildContext.ImportDir(path, 0)
|
||||
if err != nil {
|
||||
if _, noGo := err.(*build.NoGoError); noGo {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// If we are expanding "cmd", skip main
|
||||
// packages under cmd/vendor. At least as of
|
||||
// March, 2017, there is one there for the
|
||||
// vendored pprof tool.
|
||||
if pattern == "cmd" && strings.HasPrefix(pkg.ImportPath, "cmd/vendor") && pkg.Name == "main" {
|
||||
return nil
|
||||
}
|
||||
|
||||
pkgs = append(pkgs, name)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// MatchPackagesInFS returns a list of package paths matching pattern,
|
||||
// which must begin with ./ or ../
|
||||
// (see go help packages for pattern syntax).
|
||||
func (c *Context) MatchPackagesInFS(pattern string) []string {
|
||||
// Find directory to begin the scan.
|
||||
// Could be smarter but this one optimization
|
||||
// is enough for now, since ... is usually at the
|
||||
// end of a path.
|
||||
i := strings.Index(pattern, "...")
|
||||
dir, _ := path.Split(pattern[:i])
|
||||
|
||||
// pattern begins with ./ or ../.
|
||||
// path.Clean will discard the ./ but not the ../.
|
||||
// We need to preserve the ./ for pattern matching
|
||||
// and in the returned import paths.
|
||||
prefix := ""
|
||||
if strings.HasPrefix(pattern, "./") {
|
||||
prefix = "./"
|
||||
}
|
||||
match := matchPattern(pattern)
|
||||
|
||||
var pkgs []string
|
||||
filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if path == dir {
|
||||
// filepath.Walk starts at dir and recurses. For the recursive case,
|
||||
// the path is the result of filepath.Join, which calls filepath.Clean.
|
||||
// The initial case is not Cleaned, though, so we do this explicitly.
|
||||
//
|
||||
// This converts a path like "./io/" to "io". Without this step, running
|
||||
// "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io
|
||||
// package, because prepending the prefix "./" to the unclean path would
|
||||
// result in "././io", and match("././io") returns false.
|
||||
path = filepath.Clean(path)
|
||||
}
|
||||
|
||||
// Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
|
||||
_, elem := filepath.Split(path)
|
||||
dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
|
||||
if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
name := prefix + filepath.ToSlash(path)
|
||||
if !match(name) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// We keep the directory if we can import it, or if we can't import it
|
||||
// due to invalid Go source files. This means that directories containing
|
||||
// parse errors will be built (and fail) instead of being silently skipped
|
||||
// as not matching the pattern. Go 1.5 and earlier skipped, but that
|
||||
// behavior means people miss serious mistakes.
|
||||
// See golang.org/issue/11407.
|
||||
if p, err := c.BuildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) {
|
||||
if _, noGo := err.(*build.NoGoError); !noGo {
|
||||
log.Print(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
pkgs = append(pkgs, name)
|
||||
return nil
|
||||
})
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// treeCanMatchPattern(pattern)(name) reports whether
|
||||
// name or children of name can possibly match pattern.
|
||||
// Pattern is the same limited glob accepted by matchPattern.
|
||||
func treeCanMatchPattern(pattern string) func(name string) bool {
|
||||
wildCard := false
|
||||
if i := strings.Index(pattern, "..."); i >= 0 {
|
||||
wildCard = true
|
||||
pattern = pattern[:i]
|
||||
}
|
||||
return func(name string) bool {
|
||||
return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
|
||||
wildCard && strings.HasPrefix(name, pattern)
|
||||
}
|
||||
}
|
||||
|
||||
// matchPattern(pattern)(name) reports whether
|
||||
// name matches pattern. Pattern is a limited glob
|
||||
// pattern in which '...' means 'any string' and there
|
||||
// is no other special syntax.
|
||||
// Unfortunately, there are two special cases. Quoting "go help packages":
|
||||
//
|
||||
// First, /... at the end of the pattern can match an empty string,
|
||||
// so that net/... matches both net and packages in its subdirectories, like net/http.
|
||||
// Second, any slash-separted pattern element containing a wildcard never
|
||||
// participates in a match of the "vendor" element in the path of a vendored
|
||||
// package, so that ./... does not match packages in subdirectories of
|
||||
// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do.
|
||||
// Note, however, that a directory named vendor that itself contains code
|
||||
// is not a vendored package: cmd/vendor would be a command named vendor,
|
||||
// and the pattern cmd/... matches it.
|
||||
func matchPattern(pattern string) func(name string) bool {
|
||||
// Convert pattern to regular expression.
|
||||
// The strategy for the trailing /... is to nest it in an explicit ? expression.
|
||||
// The strategy for the vendor exclusion is to change the unmatchable
|
||||
// vendor strings to a disallowed code point (vendorChar) and to use
|
||||
// "(anything but that codepoint)*" as the implementation of the ... wildcard.
|
||||
// This is a bit complicated but the obvious alternative,
|
||||
// namely a hand-written search like in most shell glob matchers,
|
||||
// is too easy to make accidentally exponential.
|
||||
// Using package regexp guarantees linear-time matching.
|
||||
|
||||
const vendorChar = "\x00"
|
||||
|
||||
if strings.Contains(pattern, vendorChar) {
|
||||
return func(name string) bool { return false }
|
||||
}
|
||||
|
||||
re := regexp.QuoteMeta(pattern)
|
||||
re = replaceVendor(re, vendorChar)
|
||||
switch {
|
||||
case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`):
|
||||
re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)`
|
||||
case re == vendorChar+`/\.\.\.`:
|
||||
re = `(/vendor|/` + vendorChar + `/\.\.\.)`
|
||||
case strings.HasSuffix(re, `/\.\.\.`):
|
||||
re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?`
|
||||
}
|
||||
re = strings.Replace(re, `\.\.\.`, `[^`+vendorChar+`]*`, -1)
|
||||
|
||||
reg := regexp.MustCompile(`^` + re + `$`)
|
||||
|
||||
return func(name string) bool {
|
||||
if strings.Contains(name, vendorChar) {
|
||||
return false
|
||||
}
|
||||
return reg.MatchString(replaceVendor(name, vendorChar))
|
||||
}
|
||||
}
|
||||
|
||||
// replaceVendor returns the result of replacing
|
||||
// non-trailing vendor path elements in x with repl.
|
||||
func replaceVendor(x, repl string) string {
|
||||
if !strings.Contains(x, "vendor") {
|
||||
return x
|
||||
}
|
||||
elem := strings.Split(x, "/")
|
||||
for i := 0; i < len(elem)-1; i++ {
|
||||
if elem[i] == "vendor" {
|
||||
elem[i] = repl
|
||||
}
|
||||
}
|
||||
return strings.Join(elem, "/")
|
||||
}
|
||||
|
||||
// ImportPaths returns the import paths to use for the given command line.
|
||||
func (c *Context) ImportPaths(args []string) []string {
|
||||
args = c.ImportPathsNoDotExpansion(args)
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
if strings.Contains(a, "...") {
|
||||
if build.IsLocalImport(a) {
|
||||
out = append(out, c.allPackagesInFS(a)...)
|
||||
} else {
|
||||
out = append(out, c.allPackages(a)...)
|
||||
}
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ImportPathsNoDotExpansion returns the import paths to use for the given
|
||||
// command line, but it does no ... expansion.
|
||||
func (c *Context) ImportPathsNoDotExpansion(args []string) []string {
|
||||
if len(args) == 0 {
|
||||
return []string{"."}
|
||||
}
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
// Arguments are supposed to be import paths, but
|
||||
// as a courtesy to Windows developers, rewrite \ to /
|
||||
// in command-line arguments. Handles .\... and so on.
|
||||
if filepath.Separator == '\\' {
|
||||
a = strings.Replace(a, `\`, `/`, -1)
|
||||
}
|
||||
|
||||
// Put argument in canonical form, but preserve leading ./.
|
||||
if strings.HasPrefix(a, "./") {
|
||||
a = "./" + path.Clean(a)
|
||||
if a == "./." {
|
||||
a = "."
|
||||
}
|
||||
} else {
|
||||
a = path.Clean(a)
|
||||
}
|
||||
if IsMetaPackage(a) {
|
||||
out = append(out, c.allPackages(a)...)
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// IsMetaPackage checks if name is a reserved package name that expands to multiple packages.
|
||||
func IsMetaPackage(name string) bool {
|
||||
return name == "std" || name == "cmd" || name == "all"
|
||||
}
|
56
vendor/github.com/kisielk/gotool/match.go
generated
vendored
Normal file
56
vendor/github.com/kisielk/gotool/match.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// +build go1.9
|
||||
|
||||
package gotool
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/kisielk/gotool/internal/load"
|
||||
)
|
||||
|
||||
// importPaths returns the import paths to use for the given command line.
|
||||
func (c *Context) importPaths(args []string) []string {
|
||||
lctx := load.Context{
|
||||
BuildContext: c.BuildContext,
|
||||
GOROOTsrc: c.joinPath(c.BuildContext.GOROOT, "src"),
|
||||
}
|
||||
return lctx.ImportPaths(args)
|
||||
}
|
||||
|
||||
// joinPath calls c.BuildContext.JoinPath (if not nil) or else filepath.Join.
|
||||
//
|
||||
// It's a copy of the unexported build.Context.joinPath helper.
|
||||
func (c *Context) joinPath(elem ...string) string {
|
||||
if f := c.BuildContext.JoinPath; f != nil {
|
||||
return f(elem...)
|
||||
}
|
||||
return filepath.Join(elem...)
|
||||
}
|
317
vendor/github.com/kisielk/gotool/match18.go
generated
vendored
Normal file
317
vendor/github.com/kisielk/gotool/match18.go
generated
vendored
Normal file
@ -0,0 +1,317 @@
|
||||
// Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// +build !go1.9
|
||||
|
||||
package gotool
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/build"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// This file contains code from the Go distribution.
|
||||
|
||||
// matchPattern(pattern)(name) reports whether
|
||||
// name matches pattern. Pattern is a limited glob
|
||||
// pattern in which '...' means 'any string' and there
|
||||
// is no other special syntax.
|
||||
func matchPattern(pattern string) func(name string) bool {
|
||||
re := regexp.QuoteMeta(pattern)
|
||||
re = strings.Replace(re, `\.\.\.`, `.*`, -1)
|
||||
// Special case: foo/... matches foo too.
|
||||
if strings.HasSuffix(re, `/.*`) {
|
||||
re = re[:len(re)-len(`/.*`)] + `(/.*)?`
|
||||
}
|
||||
reg := regexp.MustCompile(`^` + re + `$`)
|
||||
return reg.MatchString
|
||||
}
|
||||
|
||||
// matchPackages returns a list of package paths matching pattern
|
||||
// (see go help packages for pattern syntax).
|
||||
func (c *Context) matchPackages(pattern string) []string {
|
||||
match := func(string) bool { return true }
|
||||
treeCanMatch := func(string) bool { return true }
|
||||
if !isMetaPackage(pattern) {
|
||||
match = matchPattern(pattern)
|
||||
treeCanMatch = treeCanMatchPattern(pattern)
|
||||
}
|
||||
|
||||
have := map[string]bool{
|
||||
"builtin": true, // ignore pseudo-package that exists only for documentation
|
||||
}
|
||||
if !c.BuildContext.CgoEnabled {
|
||||
have["runtime/cgo"] = true // ignore during walk
|
||||
}
|
||||
var pkgs []string
|
||||
|
||||
for _, src := range c.BuildContext.SrcDirs() {
|
||||
if (pattern == "std" || pattern == "cmd") && src != gorootSrc {
|
||||
continue
|
||||
}
|
||||
src = filepath.Clean(src) + string(filepath.Separator)
|
||||
root := src
|
||||
if pattern == "cmd" {
|
||||
root += "cmd" + string(filepath.Separator)
|
||||
}
|
||||
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() || path == src {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Avoid .foo, _foo, and testdata directory trees.
|
||||
_, elem := filepath.Split(path)
|
||||
if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
name := filepath.ToSlash(path[len(src):])
|
||||
if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") {
|
||||
// The name "std" is only the standard library.
|
||||
// If the name is cmd, it's the root of the command tree.
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if !treeCanMatch(name) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if have[name] {
|
||||
return nil
|
||||
}
|
||||
have[name] = true
|
||||
if !match(name) {
|
||||
return nil
|
||||
}
|
||||
_, err = c.BuildContext.ImportDir(path, 0)
|
||||
if err != nil {
|
||||
if _, noGo := err.(*build.NoGoError); noGo {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
pkgs = append(pkgs, name)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// importPathsNoDotExpansion returns the import paths to use for the given
|
||||
// command line, but it does no ... expansion.
|
||||
func (c *Context) importPathsNoDotExpansion(args []string) []string {
|
||||
if len(args) == 0 {
|
||||
return []string{"."}
|
||||
}
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
// Arguments are supposed to be import paths, but
|
||||
// as a courtesy to Windows developers, rewrite \ to /
|
||||
// in command-line arguments. Handles .\... and so on.
|
||||
if filepath.Separator == '\\' {
|
||||
a = strings.Replace(a, `\`, `/`, -1)
|
||||
}
|
||||
|
||||
// Put argument in canonical form, but preserve leading ./.
|
||||
if strings.HasPrefix(a, "./") {
|
||||
a = "./" + path.Clean(a)
|
||||
if a == "./." {
|
||||
a = "."
|
||||
}
|
||||
} else {
|
||||
a = path.Clean(a)
|
||||
}
|
||||
if isMetaPackage(a) {
|
||||
out = append(out, c.allPackages(a)...)
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// importPaths returns the import paths to use for the given command line.
|
||||
func (c *Context) importPaths(args []string) []string {
|
||||
args = c.importPathsNoDotExpansion(args)
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
if strings.Contains(a, "...") {
|
||||
if build.IsLocalImport(a) {
|
||||
out = append(out, c.allPackagesInFS(a)...)
|
||||
} else {
|
||||
out = append(out, c.allPackages(a)...)
|
||||
}
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|