Bumping k8s dependencies to 1.13
This commit is contained in:
7
vendor/golang.org/x/tools/cmd/bundle/main.go
generated
vendored
7
vendor/golang.org/x/tools/cmd/bundle/main.go
generated
vendored
@@ -105,7 +105,7 @@ var (
|
||||
outputFile = flag.String("o", "", "write output to `file` (default standard output)")
|
||||
dstPath = flag.String("dst", "", "set destination import `path` (default taken from current directory)")
|
||||
pkgName = flag.String("pkg", "", "set destination package `name` (default taken from current directory)")
|
||||
prefix = flag.String("prefix", "", "set bundled identifier prefix to `p` (default source package name + \"_\")")
|
||||
prefix = flag.String("prefix", "&_", "set bundled identifier prefix to `p` (default is \"&_\", where & stands for the original name)")
|
||||
underscore = flag.Bool("underscore", false, "rewrite golang.org to golang_org in imports; temporary workaround for golang.org/issue/16333")
|
||||
|
||||
importMap = map[string]string{}
|
||||
@@ -203,9 +203,8 @@ func bundle(src, dst, dstpkg, prefix string) ([]byte, error) {
|
||||
// Because there was a single Import call and Load succeeded,
|
||||
// InitialPackages is guaranteed to hold the sole requested package.
|
||||
info := lprog.InitialPackages()[0]
|
||||
if prefix == "" {
|
||||
pkgName := info.Files[0].Name.Name
|
||||
prefix = pkgName + "_"
|
||||
if strings.Contains(prefix, "&") {
|
||||
prefix = strings.Replace(prefix, "&", info.Files[0].Name.Name, -1)
|
||||
}
|
||||
|
||||
objsToUpdate := make(map[types.Object]bool)
|
||||
|
||||
56
vendor/golang.org/x/tools/cmd/callgraph/main.go
generated
vendored
56
vendor/golang.org/x/tools/cmd/callgraph/main.go
generated
vendored
@@ -37,7 +37,7 @@ import (
|
||||
"golang.org/x/tools/go/callgraph/cha"
|
||||
"golang.org/x/tools/go/callgraph/rta"
|
||||
"golang.org/x/tools/go/callgraph/static"
|
||||
"golang.org/x/tools/go/loader"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"golang.org/x/tools/go/pointer"
|
||||
"golang.org/x/tools/go/ssa"
|
||||
"golang.org/x/tools/go/ssa/ssautil"
|
||||
@@ -67,7 +67,7 @@ const Usage = `callgraph: display the the call graph of a Go program.
|
||||
|
||||
Usage:
|
||||
|
||||
callgraph [-algo=static|cha|rta|pta] [-test] [-format=...] <args>...
|
||||
callgraph [-algo=static|cha|rta|pta] [-test] [-format=...] package...
|
||||
|
||||
Flags:
|
||||
|
||||
@@ -118,8 +118,6 @@ Flags:
|
||||
import path of the enclosing package. Consult the go/ssa
|
||||
API documentation for details.
|
||||
|
||||
` + loader.FromArgsUsage + `
|
||||
|
||||
Examples:
|
||||
|
||||
Show the call graph of the trivial web server application:
|
||||
@@ -158,7 +156,7 @@ func init() {
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if err := doCallgraph(&build.Default, *algoFlag, *formatFlag, *testFlag, flag.Args()); err != nil {
|
||||
if err := doCallgraph("", "", *algoFlag, *formatFlag, *testFlag, flag.Args()); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "callgraph: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -166,28 +164,30 @@ func main() {
|
||||
|
||||
var stdout io.Writer = os.Stdout
|
||||
|
||||
func doCallgraph(ctxt *build.Context, algo, format string, tests bool, args []string) error {
|
||||
conf := loader.Config{Build: ctxt}
|
||||
|
||||
func doCallgraph(dir, gopath, algo, format string, tests bool, args []string) error {
|
||||
if len(args) == 0 {
|
||||
fmt.Fprintln(os.Stderr, Usage)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Use the initial packages from the command line.
|
||||
_, err := conf.FromArgs(args, tests)
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.LoadAllSyntax,
|
||||
Tests: tests,
|
||||
Dir: dir,
|
||||
}
|
||||
if gopath != "" {
|
||||
cfg.Env = append(os.Environ(), "GOPATH="+gopath) // to enable testing
|
||||
}
|
||||
initial, err := packages.Load(cfg, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load, parse and type-check the whole program.
|
||||
iprog, err := conf.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
if packages.PrintErrors(initial) > 0 {
|
||||
return fmt.Errorf("packages contain errors")
|
||||
}
|
||||
|
||||
// Create and build SSA-form program representation.
|
||||
prog := ssautil.CreateProgram(iprog, 0)
|
||||
prog, pkgs := ssautil.AllPackages(initial, 0)
|
||||
prog.Build()
|
||||
|
||||
// -- call graph construction ------------------------------------------
|
||||
@@ -221,7 +221,7 @@ func doCallgraph(ctxt *build.Context, algo, format string, tests bool, args []st
|
||||
}
|
||||
}
|
||||
|
||||
mains, err := mainPackages(prog, tests)
|
||||
mains, err := mainPackages(pkgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -237,7 +237,7 @@ func doCallgraph(ctxt *build.Context, algo, format string, tests bool, args []st
|
||||
cg = ptares.CallGraph
|
||||
|
||||
case "rta":
|
||||
mains, err := mainPackages(prog, tests)
|
||||
mains, err := mainPackages(pkgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -305,25 +305,13 @@ func doCallgraph(ctxt *build.Context, algo, format string, tests bool, args []st
|
||||
|
||||
// mainPackages returns the main packages to analyze.
|
||||
// Each resulting package is named "main" and has a main function.
|
||||
func mainPackages(prog *ssa.Program, tests bool) ([]*ssa.Package, error) {
|
||||
pkgs := prog.AllPackages() // TODO(adonovan): use only initial packages
|
||||
|
||||
// If tests, create a "testmain" package for each test.
|
||||
func mainPackages(pkgs []*ssa.Package) ([]*ssa.Package, error) {
|
||||
var mains []*ssa.Package
|
||||
if tests {
|
||||
for _, pkg := range pkgs {
|
||||
if main := prog.CreateTestMainPackage(pkg); main != nil {
|
||||
mains = append(mains, main)
|
||||
}
|
||||
for _, p := range pkgs {
|
||||
if p != nil && p.Pkg.Name() == "main" && p.Func("main") != nil {
|
||||
mains = append(mains, p)
|
||||
}
|
||||
if mains == nil {
|
||||
return nil, fmt.Errorf("no tests")
|
||||
}
|
||||
return mains, nil
|
||||
}
|
||||
|
||||
// Otherwise, use the main packages.
|
||||
mains = append(mains, ssautil.MainPackages(pkgs)...)
|
||||
if len(mains) == 0 {
|
||||
return nil, fmt.Errorf("no main packages")
|
||||
}
|
||||
|
||||
84
vendor/golang.org/x/tools/cmd/callgraph/main_test.go
generated
vendored
84
vendor/golang.org/x/tools/cmd/callgraph/main_test.go
generated
vendored
@@ -5,31 +5,44 @@
|
||||
// No testdata on Android.
|
||||
|
||||
// +build !android
|
||||
// +build go1.11
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"reflect"
|
||||
"sort"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCallgraph(t *testing.T) {
|
||||
ctxt := build.Default // copy
|
||||
ctxt.GOPATH = "testdata"
|
||||
func init() {
|
||||
// This test currently requires GOPATH mode.
|
||||
// Explicitly disabling module mode should suffix, but
|
||||
// we'll also turn off GOPROXY just for good measure.
|
||||
if err := os.Setenv("GO111MODULE", "off"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := os.Setenv("GOPROXY", "off"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
const format = "{{.Caller}} --> {{.Callee}}"
|
||||
func TestCallgraph(t *testing.T) {
|
||||
gopath, err := filepath.Abs("testdata")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, test := range []struct {
|
||||
algo, format string
|
||||
tests bool
|
||||
want []string
|
||||
algo string
|
||||
tests bool
|
||||
want []string
|
||||
}{
|
||||
{"rta", format, false, []string{
|
||||
{"rta", false, []string{
|
||||
// rta imprecisely shows cross product of {main,main2} x {C,D}
|
||||
`pkg.main --> (pkg.C).f`,
|
||||
`pkg.main --> (pkg.D).f`,
|
||||
@@ -37,7 +50,7 @@ func TestCallgraph(t *testing.T) {
|
||||
`pkg.main2 --> (pkg.C).f`,
|
||||
`pkg.main2 --> (pkg.D).f`,
|
||||
}},
|
||||
{"pta", format, false, []string{
|
||||
{"pta", false, []string{
|
||||
// pta distinguishes main->C, main2->D. Also has a root node.
|
||||
`<root> --> pkg.init`,
|
||||
`<root> --> pkg.main`,
|
||||
@@ -45,37 +58,42 @@ func TestCallgraph(t *testing.T) {
|
||||
`pkg.main --> pkg.main2`,
|
||||
`pkg.main2 --> (pkg.D).f`,
|
||||
}},
|
||||
// tests: main is not called.
|
||||
{"rta", format, true, []string{
|
||||
`pkg$testmain.init --> pkg.init`,
|
||||
// tests: both the package's main and the test's main are called.
|
||||
// The callgraph includes all the guts of the "testing" package.
|
||||
{"rta", true, []string{
|
||||
`pkg.test.main --> testing.MainStart`,
|
||||
`testing.runExample --> pkg.Example`,
|
||||
`pkg.Example --> (pkg.C).f`,
|
||||
`pkg.main --> (pkg.C).f`,
|
||||
}},
|
||||
{"pta", format, true, []string{
|
||||
`<root> --> pkg$testmain.init`,
|
||||
`<root> --> pkg.Example`,
|
||||
`pkg$testmain.init --> pkg.init`,
|
||||
{"pta", true, []string{
|
||||
`<root> --> pkg.test.main`,
|
||||
`<root> --> pkg.main`,
|
||||
`pkg.test.main --> testing.MainStart`,
|
||||
`testing.runExample --> pkg.Example`,
|
||||
`pkg.Example --> (pkg.C).f`,
|
||||
`pkg.main --> (pkg.C).f`,
|
||||
}},
|
||||
} {
|
||||
const format = "{{.Caller}} --> {{.Callee}}"
|
||||
stdout = new(bytes.Buffer)
|
||||
if err := doCallgraph(&ctxt, test.algo, test.format, test.tests, []string{"pkg"}); err != nil {
|
||||
if err := doCallgraph("testdata/src", gopath, test.algo, format, test.tests, []string{"pkg"}); err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
got := sortedLines(fmt.Sprint(stdout))
|
||||
if !reflect.DeepEqual(got, test.want) {
|
||||
t.Errorf("callgraph(%q, %q, %t):\ngot:\n%s\nwant:\n%s",
|
||||
test.algo, test.format, test.tests,
|
||||
strings.Join(got, "\n"),
|
||||
strings.Join(test.want, "\n"))
|
||||
edges := make(map[string]bool)
|
||||
for _, line := range strings.Split(fmt.Sprint(stdout), "\n") {
|
||||
edges[line] = true
|
||||
}
|
||||
for _, edge := range test.want {
|
||||
if !edges[edge] {
|
||||
t.Errorf("callgraph(%q, %t): missing edge: %s",
|
||||
test.algo, test.tests, edge)
|
||||
}
|
||||
}
|
||||
if t.Failed() {
|
||||
t.Log("got:\n", stdout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sortedLines(s string) []string {
|
||||
s = strings.TrimSpace(s)
|
||||
lines := strings.Split(s, "\n")
|
||||
sort.Strings(lines)
|
||||
return lines
|
||||
}
|
||||
|
||||
5
vendor/golang.org/x/tools/cmd/callgraph/testdata/src/pkg/pkg_test.go
generated
vendored
5
vendor/golang.org/x/tools/cmd/callgraph/testdata/src/pkg/pkg_test.go
generated
vendored
@@ -1,7 +1,10 @@
|
||||
package main
|
||||
|
||||
// Don't import "testing", it adds a lot of callgraph edges.
|
||||
// An Example function must have an "Output:" comment for the go build
|
||||
// system to generate a call to it from the test main package.
|
||||
|
||||
func Example() {
|
||||
C(0).f()
|
||||
|
||||
// Output:
|
||||
}
|
||||
|
||||
24
vendor/golang.org/x/tools/cmd/compilebench/main.go
generated
vendored
24
vendor/golang.org/x/tools/cmd/compilebench/main.go
generated
vendored
@@ -67,9 +67,9 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
@@ -144,6 +144,7 @@ func main() {
|
||||
log.Fatalf("%s env GOROOT: %v", *flagGoCmd, err)
|
||||
}
|
||||
goroot = strings.TrimSpace(string(s))
|
||||
os.Setenv("GOROOT", goroot) // for any subcommands
|
||||
|
||||
compiler = *flagCompiler
|
||||
if compiler == "" {
|
||||
@@ -250,11 +251,28 @@ func runBuild(name, dir string, count int) {
|
||||
return
|
||||
}
|
||||
|
||||
pkg, err := build.Import(dir, ".", 0)
|
||||
// Make sure dependencies needed by go tool compile are installed to GOROOT/pkg.
|
||||
out, err := exec.Command(*flagGoCmd, "build", "-i", dir).CombinedOutput()
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
log.Printf("go build -i %s: %v\n%s", dir, err, out)
|
||||
return
|
||||
}
|
||||
|
||||
// Find dir and source file list.
|
||||
var pkg struct {
|
||||
Dir string
|
||||
GoFiles []string
|
||||
}
|
||||
out, err = exec.Command(*flagGoCmd, "list", "-json", dir).Output()
|
||||
if err != nil {
|
||||
log.Printf("go list -json %s: %v\n", dir, err)
|
||||
return
|
||||
}
|
||||
if err := json.Unmarshal(out, &pkg); err != nil {
|
||||
log.Printf("go list -json %s: unmarshal: %v", dir, err)
|
||||
return
|
||||
}
|
||||
|
||||
args := []string{"-o", "_compilebench_.o"}
|
||||
if is6g {
|
||||
*flagMemprofilerate = -1
|
||||
|
||||
5
vendor/golang.org/x/tools/cmd/digraph/digraph.go
generated
vendored
5
vendor/golang.org/x/tools/cmd/digraph/digraph.go
generated
vendored
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// TODO(adonovan):
|
||||
// - support input files other than stdin
|
||||
// - suport alternative formats (AT&T GraphViz, CSV, etc),
|
||||
// - support alternative formats (AT&T GraphViz, CSV, etc),
|
||||
// a comment syntax, etc.
|
||||
// - allow queries to nest, like Blaze query language.
|
||||
//
|
||||
@@ -89,11 +89,12 @@ Example usage:
|
||||
`
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() { fmt.Fprintln(os.Stderr, Usage) }
|
||||
flag.Parse()
|
||||
|
||||
args := flag.Args()
|
||||
if len(args) == 0 {
|
||||
fmt.Println(Usage)
|
||||
fmt.Fprintln(os.Stderr, Usage)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
15
vendor/golang.org/x/tools/cmd/fiximports/main.go
generated
vendored
15
vendor/golang.org/x/tools/cmd/fiximports/main.go
generated
vendored
@@ -491,15 +491,18 @@ func list(args ...string) ([]*listPackage, error) {
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
var cwd string
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
cwd, err = os.Getwd()
|
||||
// cwd contains the current working directory of the tool.
|
||||
//
|
||||
// It is initialized directly so that its value will be set for any other
|
||||
// package variables or init functions that depend on it, such as the gopath
|
||||
// variable in main_test.go.
|
||||
var cwd string = func() string {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatalf("os.Getwd: %v", err)
|
||||
}
|
||||
}
|
||||
return cwd
|
||||
}()
|
||||
|
||||
// shortPath returns an absolute or relative name for path, whatever is shorter.
|
||||
// Plundered from $GOROOT/src/cmd/go/build.go.
|
||||
|
||||
26
vendor/golang.org/x/tools/cmd/fiximports/main_test.go
generated
vendored
26
vendor/golang.org/x/tools/cmd/fiximports/main_test.go
generated
vendored
@@ -10,6 +10,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@@ -32,11 +33,25 @@ import (
|
||||
// titanic.biz/bar -- domain is sinking; package has jumped ship to new.com/bar
|
||||
// titanic.biz/foo -- domain is sinking but package has no import comment yet
|
||||
|
||||
func TestFixImports(t *testing.T) {
|
||||
gopath := filepath.Join(cwd, "testdata")
|
||||
var gopath = filepath.Join(cwd, "testdata")
|
||||
|
||||
func init() {
|
||||
if err := os.Setenv("GOPATH", gopath); err != nil {
|
||||
t.Fatalf("os.Setenv: %v", err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// This test currently requires GOPATH mode.
|
||||
// Explicitly disabling module mode should suffix, but
|
||||
// we'll also turn off GOPROXY just for good measure.
|
||||
if err := os.Setenv("GO111MODULE", "off"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := os.Setenv("GOPROXY", "off"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFixImports(t *testing.T) {
|
||||
defer func() {
|
||||
stderr = os.Stderr
|
||||
*badDomains = "code.google.com"
|
||||
@@ -224,11 +239,6 @@ import (
|
||||
|
||||
// TestDryRun tests that the -n flag suppresses calls to writeFile.
|
||||
func TestDryRun(t *testing.T) {
|
||||
gopath := filepath.Join(cwd, "testdata")
|
||||
if err := os.Setenv("GOPATH", gopath); err != nil {
|
||||
t.Fatalf("os.Setenv: %v", err)
|
||||
}
|
||||
|
||||
*dryrun = true
|
||||
defer func() { *dryrun = false }() // restore
|
||||
stderr = new(bytes.Buffer)
|
||||
|
||||
36
vendor/golang.org/x/tools/cmd/godex/print.go
generated
vendored
36
vendor/golang.org/x/tools/cmd/godex/print.go
generated
vendored
@@ -7,7 +7,7 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
exact "go/constant"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io"
|
||||
@@ -213,9 +213,9 @@ func (p *printer) printDecl(keyword string, n int, printGroup func()) {
|
||||
|
||||
// absInt returns the absolute value of v as a *big.Int.
|
||||
// v must be a numeric value.
|
||||
func absInt(v exact.Value) *big.Int {
|
||||
func absInt(v constant.Value) *big.Int {
|
||||
// compute big-endian representation of v
|
||||
b := exact.Bytes(v) // little-endian
|
||||
b := constant.Bytes(v) // little-endian
|
||||
for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
@@ -229,14 +229,14 @@ var (
|
||||
|
||||
// floatString returns the string representation for a
|
||||
// numeric value v in normalized floating-point format.
|
||||
func floatString(v exact.Value) string {
|
||||
if exact.Sign(v) == 0 {
|
||||
func floatString(v constant.Value) string {
|
||||
if constant.Sign(v) == 0 {
|
||||
return "0.0"
|
||||
}
|
||||
// x != 0
|
||||
|
||||
// convert |v| into a big.Rat x
|
||||
x := new(big.Rat).SetFrac(absInt(exact.Num(v)), absInt(exact.Denom(v)))
|
||||
x := new(big.Rat).SetFrac(absInt(constant.Num(v)), absInt(constant.Denom(v)))
|
||||
|
||||
// normalize x and determine exponent e
|
||||
// (This is not very efficient, but also not speed-critical.)
|
||||
@@ -272,7 +272,7 @@ func floatString(v exact.Value) string {
|
||||
if e != 0 {
|
||||
s += fmt.Sprintf("e%+d", e)
|
||||
}
|
||||
if exact.Sign(v) < 0 {
|
||||
if constant.Sign(v) < 0 {
|
||||
s = "-" + s
|
||||
}
|
||||
|
||||
@@ -286,29 +286,29 @@ func floatString(v exact.Value) string {
|
||||
// valString returns the string representation for the value v.
|
||||
// Setting floatFmt forces an integer value to be formatted in
|
||||
// normalized floating-point format.
|
||||
// TODO(gri) Move this code into package exact.
|
||||
func valString(v exact.Value, floatFmt bool) string {
|
||||
// TODO(gri) Move this code into package constant.
|
||||
func valString(v constant.Value, floatFmt bool) string {
|
||||
switch v.Kind() {
|
||||
case exact.Int:
|
||||
case constant.Int:
|
||||
if floatFmt {
|
||||
return floatString(v)
|
||||
}
|
||||
case exact.Float:
|
||||
case constant.Float:
|
||||
return floatString(v)
|
||||
case exact.Complex:
|
||||
re := exact.Real(v)
|
||||
im := exact.Imag(v)
|
||||
case constant.Complex:
|
||||
re := constant.Real(v)
|
||||
im := constant.Imag(v)
|
||||
var s string
|
||||
if exact.Sign(re) != 0 {
|
||||
if constant.Sign(re) != 0 {
|
||||
s = floatString(re)
|
||||
if exact.Sign(im) >= 0 {
|
||||
if constant.Sign(im) >= 0 {
|
||||
s += " + "
|
||||
} else {
|
||||
s += " - "
|
||||
im = exact.UnaryOp(token.SUB, im, 0) // negate im
|
||||
im = constant.UnaryOp(token.SUB, im, 0) // negate im
|
||||
}
|
||||
}
|
||||
// im != 0, otherwise v would be exact.Int or exact.Float
|
||||
// im != 0, otherwise v would be constant.Int or constant.Float
|
||||
return s + floatString(im) + "i"
|
||||
}
|
||||
return v.String()
|
||||
|
||||
3
vendor/golang.org/x/tools/cmd/godoc/.gitignore
generated
vendored
Normal file
3
vendor/golang.org/x/tools/cmd/godoc/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
index.split.*
|
||||
godoc.index
|
||||
godoc.zip
|
||||
67
vendor/golang.org/x/tools/cmd/godoc/Dockerfile.prod
generated
vendored
Normal file
67
vendor/golang.org/x/tools/cmd/godoc/Dockerfile.prod
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
# Builder
|
||||
#########
|
||||
|
||||
FROM golang:1.11 AS build
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
zip # required for generate-index.bash
|
||||
|
||||
# Check out the desired version of Go, both to build the godoc binary and serve
|
||||
# as the goroot for content serving.
|
||||
ARG GO_REF
|
||||
RUN test -n "$GO_REF" # GO_REF is required.
|
||||
RUN git clone --single-branch --depth=1 -b $GO_REF https://go.googlesource.com/go /goroot
|
||||
RUN cd /goroot/src && ./make.bash
|
||||
|
||||
ENV GOROOT /goroot
|
||||
ENV PATH=/goroot/bin:$PATH
|
||||
|
||||
RUN go version
|
||||
|
||||
RUN go get -v -d \
|
||||
golang.org/x/net/context \
|
||||
google.golang.org/appengine \
|
||||
cloud.google.com/go/datastore \
|
||||
golang.org/x/build \
|
||||
github.com/gomodule/redigo/redis
|
||||
|
||||
COPY . /go/src/golang.org/x/tools
|
||||
|
||||
WORKDIR /go/src/golang.org/x/tools/cmd/godoc
|
||||
RUN GODOC_DOCSET=/goroot ./generate-index.bash
|
||||
|
||||
RUN go build -o /godoc -tags=golangorg golang.org/x/tools/cmd/godoc
|
||||
|
||||
# Clean up goroot for the final image.
|
||||
RUN cd /goroot && git clean -xdf
|
||||
|
||||
# Add build metadata.
|
||||
RUN cd /goroot && echo "go repo HEAD: $(git rev-parse HEAD)" >> /goroot/buildinfo
|
||||
RUN echo "requested go ref: ${GO_REF}" >> /goroot/buildinfo
|
||||
ARG TOOLS_HEAD
|
||||
RUN echo "x/tools HEAD: ${TOOLS_HEAD}" >> /goroot/buildinfo
|
||||
ARG TOOLS_CLEAN
|
||||
RUN echo "x/tools clean: ${TOOLS_CLEAN}" >> /goroot/buildinfo
|
||||
ARG DOCKER_TAG
|
||||
RUN echo "image: ${DOCKER_TAG}" >> /goroot/buildinfo
|
||||
ARG BUILD_ENV
|
||||
RUN echo "build env: ${BUILD_ENV}" >> /goroot/buildinfo
|
||||
|
||||
RUN rm -rf /goroot/.git
|
||||
|
||||
# Final image
|
||||
#############
|
||||
|
||||
FROM gcr.io/distroless/base
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=build /godoc /app/
|
||||
COPY --from=build /go/src/golang.org/x/tools/cmd/godoc/hg-git-mapping.bin /app/
|
||||
|
||||
COPY --from=build /goroot /goroot
|
||||
ENV GOROOT /goroot
|
||||
|
||||
COPY --from=build /go/src/golang.org/x/tools/cmd/godoc/index.split.* /app/
|
||||
ENV GODOC_INDEX_GLOB index.split.*
|
||||
|
||||
CMD ["/app/godoc"]
|
||||
80
vendor/golang.org/x/tools/cmd/godoc/Makefile
generated
vendored
Normal file
80
vendor/golang.org/x/tools/cmd/godoc/Makefile
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
# Copyright 2018 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.
|
||||
|
||||
.PHONY: usage
|
||||
|
||||
GO_REF ?= release-branch.go1.11
|
||||
TOOLS_HEAD := $(shell git rev-parse HEAD)
|
||||
TOOLS_CLEAN := $(shell (git status --porcelain | grep -q .) && echo dirty || echo clean)
|
||||
ifeq ($(TOOLS_CLEAN),clean)
|
||||
DOCKER_VERSION ?= $(TOOLS_HEAD)
|
||||
else
|
||||
DOCKER_VERSION ?= $(TOOLS_HEAD)-dirty
|
||||
endif
|
||||
GCP_PROJECT := golang-org
|
||||
DOCKER_TAG := gcr.io/$(GCP_PROJECT)/godoc:$(DOCKER_VERSION)
|
||||
|
||||
usage:
|
||||
@echo "See Makefile and README.godoc-app"
|
||||
@exit 1
|
||||
|
||||
cloud-build: Dockerfile.prod
|
||||
gcloud builds submit \
|
||||
--project=$(GCP_PROJECT) \
|
||||
--config=cloudbuild.yaml \
|
||||
--substitutions=_GO_REF=$(GO_REF),_TOOLS_HEAD=$(TOOLS_HEAD),_TOOLS_CLEAN=$(TOOLS_CLEAN),_DOCKER_TAG=$(DOCKER_TAG) \
|
||||
../.. # source code
|
||||
|
||||
docker-build: Dockerfile.prod
|
||||
# NOTE(cbro): move up in directory to include entire tools repo.
|
||||
# NOTE(cbro): any changes made to this command must also be made in cloudbuild.yaml.
|
||||
cd ../..; docker build \
|
||||
-f=cmd/godoc/Dockerfile.prod \
|
||||
--build-arg=GO_REF=$(GO_REF) \
|
||||
--build-arg=TOOLS_HEAD=$(TOOLS_HEAD) \
|
||||
--build-arg=TOOLS_CLEAN=$(TOOLS_CLEAN) \
|
||||
--build-arg=DOCKER_TAG=$(DOCKER_TAG) \
|
||||
--build-arg=BUILD_ENV=local \
|
||||
--tag=$(DOCKER_TAG) \
|
||||
.
|
||||
|
||||
docker-push: docker-build
|
||||
docker push $(DOCKER_TAG)
|
||||
|
||||
deploy:
|
||||
gcloud -q app deploy app.prod.yaml \
|
||||
--project=$(GCP_PROJECT) \
|
||||
--no-promote \
|
||||
--image-url=$(DOCKER_TAG)
|
||||
|
||||
get-latest-url:
|
||||
@gcloud app versions list \
|
||||
--service=default \
|
||||
--project=$(GCP_PROJECT) \
|
||||
--sort-by=~version.createTime \
|
||||
--format='value(version.versionUrl)' \
|
||||
--limit 1 | cut -f1 # NOTE(cbro): gcloud prints out createTime as the second field.
|
||||
|
||||
get-latest-id:
|
||||
@gcloud app versions list \
|
||||
--service=default \
|
||||
--project=$(GCP_PROJECT) \
|
||||
--sort-by=~version.createTime \
|
||||
--format='value(version.id)' \
|
||||
--limit 1 | cut -f1 # NOTE(cbro): gcloud prints out createTime as the second field.
|
||||
|
||||
regtest:
|
||||
go test -v \
|
||||
-regtest.host=$(shell make get-latest-url) \
|
||||
-run=Live
|
||||
|
||||
publish: regtest
|
||||
gcloud -q app services set-traffic default \
|
||||
--splits=$(shell make get-latest-id)=1 \
|
||||
--project=$(GCP_PROJECT)
|
||||
|
||||
@echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
@echo Stop and/or delete old versions:
|
||||
@echo "https://console.cloud.google.com/appengine/versions?project=$(GCP_PROJECT)&serviceId=default&versionssize=50"
|
||||
@echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
104
vendor/golang.org/x/tools/cmd/godoc/README.godoc-app
generated
vendored
104
vendor/golang.org/x/tools/cmd/godoc/README.godoc-app
generated
vendored
@@ -1,56 +1,94 @@
|
||||
godoc on appengine
|
||||
------------------
|
||||
godoc on Google App Engine
|
||||
==========================
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
* Go appengine SDK
|
||||
https://developers.google.com/appengine/downloads#Google_App_Engine_SDK_for_Go
|
||||
* Google Cloud SDK
|
||||
https://cloud.google.com/sdk/
|
||||
|
||||
* Go sources at tip under $GOROOT
|
||||
* Redis
|
||||
|
||||
* Godoc sources at tip inside $GOPATH
|
||||
* Go sources under $GOROOT
|
||||
|
||||
* Godoc sources inside $GOPATH
|
||||
(go get -d golang.org/x/tools/cmd/godoc)
|
||||
|
||||
|
||||
Directory structure
|
||||
-------------------
|
||||
Running locally, in production mode
|
||||
-----------------------------------
|
||||
|
||||
* Let $APPDIR be the directory containing the app engine files.
|
||||
(e.g., $APPDIR=$HOME/godoc-app)
|
||||
Build the app:
|
||||
|
||||
* $APPDIR contains the following entries (this may change depending on
|
||||
app-engine release and version of godoc):
|
||||
go build -tags golangorg
|
||||
|
||||
app.yaml
|
||||
golang.org/x/tools/cmd/godoc
|
||||
godoc.zip
|
||||
index.split.*
|
||||
Run the app:
|
||||
|
||||
* The app.yaml file is set up per app engine documentation.
|
||||
For instance:
|
||||
./godoc
|
||||
|
||||
application: godoc-app
|
||||
version: 1
|
||||
runtime: go
|
||||
api_version: go1
|
||||
godoc should come up at http://localhost:8080
|
||||
|
||||
handlers:
|
||||
- url: /.*
|
||||
script: _go_app
|
||||
Use the PORT environment variable to change the port:
|
||||
|
||||
PORT=8081 ./godoc
|
||||
|
||||
Running locally, in production mode, using Docker
|
||||
-------------------------------------------------
|
||||
|
||||
Build the app's Docker container:
|
||||
|
||||
make docker-build
|
||||
|
||||
Make sure redis is running on port 6379:
|
||||
|
||||
$ echo PING | nc localhost 6379
|
||||
+PONG
|
||||
^C
|
||||
|
||||
Run the datastore emulator:
|
||||
|
||||
gcloud beta emulators datastore start --project golang-org
|
||||
|
||||
In another terminal window, run the container:
|
||||
|
||||
$(gcloud beta emulators datastore env-init)
|
||||
|
||||
docker run --rm \
|
||||
--net host \
|
||||
--env GODOC_REDIS_ADDR=localhost:6379 \
|
||||
--env DATASTORE_EMULATOR_HOST=$DATASTORE_EMULATOR_HOST \
|
||||
--env DATASTORE_PROJECT_ID=$DATASTORE_PROJECT_ID \
|
||||
gcr.io/golang-org/godoc
|
||||
|
||||
godoc should come up at http://localhost:8080
|
||||
|
||||
|
||||
Configuring and running godoc
|
||||
-----------------------------
|
||||
Deploying to golang.org
|
||||
-----------------------
|
||||
|
||||
To configure godoc, run
|
||||
Make sure you're signed in to gcloud:
|
||||
|
||||
bash setup-godoc-app.bash
|
||||
gcloud auth login
|
||||
|
||||
to prepare an $APPDIR as described above. See the script for details on usage.
|
||||
Build the image, push it to gcr.io, and deploy to Flex:
|
||||
|
||||
To run godoc locally, using the App Engine development server, run
|
||||
make cloud-build deploy
|
||||
|
||||
<path to go_appengine>/dev_appserver.py $APPDIR
|
||||
Point the load balancer to the newly deployed version:
|
||||
(This also runs regression tests)
|
||||
|
||||
godoc should come up at http://localhost:8080 .
|
||||
make publish
|
||||
|
||||
Stop and/or delete down any very old versions. (Stopped versions can be re-started.)
|
||||
Keep at least one older verson to roll back to, just in case.
|
||||
You can also migrate traffic to the new version via this UI.
|
||||
|
||||
https://console.cloud.google.com/appengine/versions?project=golang-org&serviceId=default&versionssize=50
|
||||
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
Ensure the Cloud SDK is on your PATH and you have the app-engine-go component
|
||||
installed (gcloud components install app-engine-go) and your components are
|
||||
up-to-date (gcloud components update)
|
||||
|
||||
13
vendor/golang.org/x/tools/cmd/godoc/app.dev.yaml
generated
vendored
Normal file
13
vendor/golang.org/x/tools/cmd/godoc/app.dev.yaml
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
runtime: go
|
||||
api_version: go1
|
||||
instance_class: F4_1G
|
||||
|
||||
handlers:
|
||||
- url: /s
|
||||
script: _go_app
|
||||
login: admin
|
||||
- url: /dl/init
|
||||
script: _go_app
|
||||
login: admin
|
||||
- url: /.*
|
||||
script: _go_app
|
||||
16
vendor/golang.org/x/tools/cmd/godoc/app.prod.yaml
generated
vendored
Normal file
16
vendor/golang.org/x/tools/cmd/godoc/app.prod.yaml
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
runtime: custom
|
||||
env: flex
|
||||
|
||||
env_variables:
|
||||
GODOC_PROD: true
|
||||
GODOC_ENFORCE_HOSTS: true
|
||||
GODOC_REDIS_ADDR: 10.0.0.4:6379 # instance "gophercache"
|
||||
GODOC_ANALYTICS: UA-11222381-2
|
||||
DATASTORE_PROJECT_ID: golang-org
|
||||
|
||||
network:
|
||||
name: golang
|
||||
|
||||
resources:
|
||||
cpu: 4
|
||||
memory_gb: 7.50
|
||||
109
vendor/golang.org/x/tools/cmd/godoc/appinit.go
generated
vendored
109
vendor/golang.org/x/tools/cmd/godoc/appinit.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build appengine
|
||||
// +build golangorg
|
||||
|
||||
package main
|
||||
|
||||
@@ -11,25 +11,46 @@ package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"context"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/godoc"
|
||||
"golang.org/x/tools/godoc/dl"
|
||||
"golang.org/x/tools/godoc/proxy"
|
||||
"golang.org/x/tools/godoc/redirect"
|
||||
"golang.org/x/tools/godoc/short"
|
||||
"golang.org/x/tools/godoc/static"
|
||||
"golang.org/x/tools/godoc/vfs"
|
||||
"golang.org/x/tools/godoc/vfs/gatefs"
|
||||
"golang.org/x/tools/godoc/vfs/mapfs"
|
||||
"golang.org/x/tools/godoc/vfs/zipfs"
|
||||
|
||||
"google.golang.org/appengine"
|
||||
"cloud.google.com/go/datastore"
|
||||
"golang.org/x/tools/internal/memcache"
|
||||
)
|
||||
|
||||
func init() {
|
||||
enforceHosts = !appengine.IsDevAppServer()
|
||||
func main() {
|
||||
log.SetFlags(log.Lshortfile | log.LstdFlags)
|
||||
|
||||
var (
|
||||
// .zip filename
|
||||
zipFilename = os.Getenv("GODOC_ZIP")
|
||||
|
||||
// goroot directory in .zip file
|
||||
zipGoroot = os.Getenv("GODOC_ZIP_PREFIX")
|
||||
|
||||
// glob pattern describing search index files
|
||||
// (if empty, the index is built at run-time)
|
||||
indexFilenames = os.Getenv("GODOC_INDEX_GLOB")
|
||||
)
|
||||
|
||||
playEnabled = true
|
||||
|
||||
log.Println("initializing godoc ...")
|
||||
@@ -37,16 +58,20 @@ func init() {
|
||||
log.Printf(".zip GOROOT = %s", zipGoroot)
|
||||
log.Printf("index files = %s", indexFilenames)
|
||||
|
||||
goroot := path.Join("/", zipGoroot) // fsHttp paths are relative to '/'
|
||||
|
||||
// read .zip file and set up file systems
|
||||
const zipfile = zipFilename
|
||||
rc, err := zip.OpenReader(zipfile)
|
||||
if err != nil {
|
||||
log.Fatalf("%s: %s\n", zipfile, err)
|
||||
if zipFilename != "" {
|
||||
goroot := path.Join("/", zipGoroot) // fsHttp paths are relative to '/'
|
||||
// read .zip file and set up file systems
|
||||
rc, err := zip.OpenReader(zipFilename)
|
||||
if err != nil {
|
||||
log.Fatalf("%s: %s\n", zipFilename, err)
|
||||
}
|
||||
// rc is never closed (app running forever)
|
||||
fs.Bind("/", zipfs.New(rc, zipFilename), goroot, vfs.BindReplace)
|
||||
} else {
|
||||
rootfs := gatefs.New(vfs.OS(runtime.GOROOT()), make(chan bool, 20))
|
||||
fs.Bind("/", rootfs, "/", vfs.BindReplace)
|
||||
}
|
||||
// rc is never closed (app running forever)
|
||||
fs.Bind("/", zipfs.New(rc, zipFilename), goroot, vfs.BindReplace)
|
||||
|
||||
fs.Bind("/lib/godoc", mapfs.New(static.Files), "/", vfs.BindReplace)
|
||||
|
||||
corpus := godoc.NewCorpus(fs)
|
||||
@@ -58,25 +83,73 @@ func init() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
corpus.IndexDirectory = indexDirectoryDefault
|
||||
go corpus.RunIndexer()
|
||||
corpus.InitVersionInfo()
|
||||
if indexFilenames != "" {
|
||||
corpus.RunIndexer()
|
||||
} else {
|
||||
go corpus.RunIndexer()
|
||||
}
|
||||
|
||||
pres = godoc.NewPresentation(corpus)
|
||||
pres.TabWidth = 8
|
||||
pres.ShowPlayground = true
|
||||
pres.ShowExamples = true
|
||||
pres.DeclLinks = true
|
||||
pres.NotesRx = regexp.MustCompile("BUG")
|
||||
pres.GoogleAnalytics = os.Getenv("GODOC_ANALYTICS")
|
||||
|
||||
readTemplates(pres, true)
|
||||
readTemplates(pres)
|
||||
|
||||
datastoreClient, memcacheClient := getClients()
|
||||
|
||||
// NOTE(cbro): registerHandlers registers itself against DefaultServeMux.
|
||||
// The mux returned has host enforcement, so it's important to register
|
||||
// against this mux and not DefaultServeMux.
|
||||
mux := registerHandlers(pres)
|
||||
dl.RegisterHandlers(mux)
|
||||
short.RegisterHandlers(mux)
|
||||
dl.RegisterHandlers(mux, datastoreClient, memcacheClient)
|
||||
short.RegisterHandlers(mux, datastoreClient, memcacheClient)
|
||||
|
||||
// Register /compile and /share handlers against the default serve mux
|
||||
// so that other app modules can make plain HTTP requests to those
|
||||
// hosts. (For reasons, HTTPS communication between modules is broken.)
|
||||
proxy.RegisterHandlers(http.DefaultServeMux)
|
||||
|
||||
http.HandleFunc("/_ah/health", func(w http.ResponseWriter, r *http.Request) {
|
||||
io.WriteString(w, "ok")
|
||||
})
|
||||
|
||||
http.HandleFunc("/robots.txt", func(w http.ResponseWriter, r *http.Request) {
|
||||
io.WriteString(w, "User-agent: *\nDisallow: /search\n")
|
||||
})
|
||||
|
||||
if err := redirect.LoadChangeMap("hg-git-mapping.bin"); err != nil {
|
||||
log.Fatalf("LoadChangeMap: %v", err)
|
||||
}
|
||||
|
||||
log.Println("godoc initialization complete")
|
||||
|
||||
// TODO(cbro): add instrumentation via opencensus.
|
||||
port := "8080"
|
||||
if p := os.Getenv("PORT"); p != "" { // PORT is set by GAE flex.
|
||||
port = p
|
||||
}
|
||||
log.Fatal(http.ListenAndServe(":"+port, nil))
|
||||
}
|
||||
|
||||
func getClients() (*datastore.Client, *memcache.Client) {
|
||||
ctx := context.Background()
|
||||
|
||||
datastoreClient, err := datastore.NewClient(ctx, "")
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "missing project") {
|
||||
log.Fatalf("Missing datastore project. Set the DATASTORE_PROJECT_ID env variable. Use `gcloud beta emulators datastore` to start a local datastore.")
|
||||
}
|
||||
log.Fatalf("datastore.NewClient: %v.", err)
|
||||
}
|
||||
|
||||
redisAddr := os.Getenv("GODOC_REDIS_ADDR")
|
||||
if redisAddr == "" {
|
||||
log.Fatalf("Missing redis server for godoc in production mode. set GODOC_REDIS_ADDR environment variable.")
|
||||
}
|
||||
memcacheClient := memcache.New(redisAddr)
|
||||
return datastoreClient, memcacheClient
|
||||
}
|
||||
|
||||
7
vendor/golang.org/x/tools/cmd/godoc/blog.go
generated
vendored
7
vendor/golang.org/x/tools/cmd/godoc/blog.go
generated
vendored
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
const (
|
||||
blogRepo = "golang.org/x/blog"
|
||||
blogURL = "http://blog.golang.org/"
|
||||
blogURL = "https://blog.golang.org/"
|
||||
blogPath = "/blog/"
|
||||
)
|
||||
|
||||
@@ -42,10 +42,11 @@ func init() {
|
||||
}
|
||||
|
||||
func blogInit(host string) {
|
||||
// Binary distributions will include the blog content in "/blog".
|
||||
// Binary distributions included the blog content in "/blog".
|
||||
// We stopped including this in Go 1.11.
|
||||
root := filepath.Join(runtime.GOROOT(), "blog")
|
||||
|
||||
// Prefer content from go.blog repository if present.
|
||||
// Prefer content from the golang.org/x/blog repository if present.
|
||||
if pkg, err := build.Import(blogRepo, "", build.FindOnly); err == nil {
|
||||
root = pkg.Dir
|
||||
}
|
||||
|
||||
25
vendor/golang.org/x/tools/cmd/godoc/cloudbuild.yaml
generated
vendored
Normal file
25
vendor/golang.org/x/tools/cmd/godoc/cloudbuild.yaml
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright 2018 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.
|
||||
|
||||
# NOTE(cbro): any changes to the docker command must also be
|
||||
# made in docker-build in the Makefile.
|
||||
#
|
||||
# Variable substitutions must have a preceding underscore. See:
|
||||
# https://cloud.google.com/cloud-build/docs/configuring-builds/substitute-variable-values#using_user-defined_substitutions
|
||||
steps:
|
||||
- name: 'gcr.io/cloud-builders/docker'
|
||||
args: [
|
||||
'build',
|
||||
'-f=cmd/godoc/Dockerfile.prod',
|
||||
'--build-arg=GO_REF=${_GO_REF}',
|
||||
'--build-arg=TOOLS_HEAD=${_TOOLS_HEAD}',
|
||||
'--build-arg=TOOLS_CLEAN=${_TOOLS_CLEAN}',
|
||||
'--build-arg=DOCKER_TAG=${_DOCKER_TAG}',
|
||||
'--build-arg=BUILD_ENV=cloudbuild',
|
||||
'--tag=${_DOCKER_TAG}',
|
||||
'.',
|
||||
]
|
||||
images: ['${_DOCKER_TAG}']
|
||||
options:
|
||||
machineType: 'N1_HIGHCPU_8' # building the godoc index takes a lot of memory.
|
||||
2
vendor/golang.org/x/tools/cmd/godoc/dl.go
generated
vendored
2
vendor/golang.org/x/tools/cmd/godoc/dl.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !appengine
|
||||
// +build !golangorg
|
||||
|
||||
package main
|
||||
|
||||
|
||||
69
vendor/golang.org/x/tools/cmd/godoc/doc.go
generated
vendored
69
vendor/golang.org/x/tools/cmd/godoc/doc.go
generated
vendored
@@ -6,50 +6,19 @@
|
||||
|
||||
Godoc extracts and generates documentation for Go programs.
|
||||
|
||||
It has two modes.
|
||||
|
||||
Without the -http flag, it runs in command-line mode and prints plain text
|
||||
documentation to standard output and exits. If both a library package and
|
||||
a command with the same name exists, using the prefix cmd/ will force
|
||||
documentation on the command rather than the library package. If the -src
|
||||
flag is specified, godoc prints the exported interface of a package in Go
|
||||
source form, or the implementation of a specific exported language entity:
|
||||
|
||||
godoc fmt # documentation for package fmt
|
||||
godoc fmt Printf # documentation for fmt.Printf
|
||||
godoc cmd/go # force documentation for the go command
|
||||
godoc -src fmt # fmt package interface in Go source form
|
||||
godoc -src fmt Printf # implementation of fmt.Printf
|
||||
|
||||
In command-line mode, the -q flag enables search queries against a godoc running
|
||||
as a webserver. If no explicit server address is specified with the -server flag,
|
||||
godoc first tries localhost:6060 and then http://golang.org.
|
||||
|
||||
godoc -q Reader
|
||||
godoc -q math.Sin
|
||||
godoc -server=:6060 -q sin
|
||||
|
||||
With the -http flag, it runs as a web server and presents the documentation as a
|
||||
It runs as a web server and presents the documentation as a
|
||||
web page.
|
||||
|
||||
godoc -http=:6060
|
||||
|
||||
Usage:
|
||||
|
||||
godoc [flag] package [name ...]
|
||||
godoc [flag]
|
||||
|
||||
The flags are:
|
||||
|
||||
-v
|
||||
verbose mode
|
||||
-q
|
||||
arguments are considered search queries: a legal query is a
|
||||
single identifier (such as ToLower) or a qualified identifier
|
||||
(such as math.Sin)
|
||||
-src
|
||||
print (exported) source in command-line mode
|
||||
-tabwidth=4
|
||||
width of tabs in units of spaces
|
||||
-timestamps=true
|
||||
show timestamps with directory listings
|
||||
-index
|
||||
@@ -63,7 +32,12 @@ The flags are:
|
||||
to the indexer (the indexer will never finish), a value of 1.0
|
||||
means that index creation is running at full throttle (other
|
||||
goroutines may get no time while the index is built)
|
||||
-links=true:
|
||||
-index_interval=0
|
||||
interval of indexing; a value of 0 sets it to 5 minutes, a
|
||||
negative value indexes only once at startup
|
||||
-play=false
|
||||
enable playground
|
||||
-links=true
|
||||
link identifiers to their declarations
|
||||
-write_index=false
|
||||
write index to a file; the file name must be specified with
|
||||
@@ -74,21 +48,17 @@ The flags are:
|
||||
-notes="BUG"
|
||||
regular expression matching note markers to show
|
||||
(e.g., "BUG|TODO", ".*")
|
||||
-html
|
||||
print HTML in command-line mode
|
||||
-goroot=$GOROOT
|
||||
Go root directory
|
||||
-http=addr
|
||||
HTTP service address (e.g., '127.0.0.1:6060' or just ':6060')
|
||||
-server=addr
|
||||
webserver address for command line searches
|
||||
-analysis=type,pointer
|
||||
comma-separated list of analyses to perform
|
||||
"type": display identifier resolution, type info, method sets,
|
||||
'implements', and static callees
|
||||
"pointer": display channel peers, callers and dynamic callees
|
||||
(significantly slower)
|
||||
See http://golang.org/lib/godoc/analysis/help.html for details.
|
||||
See https://golang.org/lib/godoc/analysis/help.html for details.
|
||||
-templates=""
|
||||
directory containing alternate template files; if set,
|
||||
the directory may provide alternative template files
|
||||
@@ -103,7 +73,7 @@ By default, godoc looks at the packages it finds via $GOROOT and $GOPATH (if set
|
||||
This behavior can be altered by providing an alternative $GOROOT with the -goroot
|
||||
flag.
|
||||
|
||||
When godoc runs as a web server and -index is set, a search index is maintained.
|
||||
When the -index flag is set, a search index is maintained.
|
||||
The index is created at startup.
|
||||
|
||||
The index contains both identifier and full text search information (searchable
|
||||
@@ -111,10 +81,8 @@ via regular expressions). The maximum number of full text search results shown
|
||||
can be set with the -maxresults flag; if set to 0, no full text results are
|
||||
shown, and only an identifier index but no full text search index is created.
|
||||
|
||||
By default, godoc uses the system's GOOS/GOARCH; in command-line mode you can
|
||||
set the GOOS/GOARCH environment variables to get output for the system specified.
|
||||
If -http was specified you can provide the URL parameters "GOOS" and "GOARCH"
|
||||
to set the output on the web page.
|
||||
By default, godoc uses the system's GOOS/GOARCH. You can provide the URL parameters
|
||||
"GOOS" and "GOARCH" to set the output on the web page for the target system.
|
||||
|
||||
The presentation mode of web pages served by godoc can be controlled with the
|
||||
"m" URL parameter; it accepts a comma-separated list of flag names as value:
|
||||
@@ -122,12 +90,9 @@ The presentation mode of web pages served by godoc can be controlled with the
|
||||
all show documentation for all declarations, not just the exported ones
|
||||
methods show all embedded methods, not just those of unexported anonymous fields
|
||||
src show the original source code rather then the extracted documentation
|
||||
text present the page in textual (command-line) form rather than HTML
|
||||
flat present flat (not indented) directory listings using full paths
|
||||
|
||||
For instance, http://golang.org/pkg/math/big/?m=all,text shows the documentation
|
||||
for all (not just the exported) declarations of package big, in textual form (as
|
||||
it would appear when using godoc from the command line: "godoc -src math/big .*").
|
||||
For instance, https://golang.org/pkg/math/big/?m=all shows the documentation
|
||||
for all (not just the exported) declarations of package big.
|
||||
|
||||
By default, godoc serves files from the file system of the underlying OS.
|
||||
Instead, a .zip file may be provided via the -zip flag, which contains
|
||||
@@ -143,11 +108,11 @@ one may run godoc as follows:
|
||||
godoc -http=:6060 -zip=go.zip -goroot=$HOME/go
|
||||
|
||||
Godoc documentation is converted to HTML or to text using the go/doc package;
|
||||
see http://golang.org/pkg/go/doc/#ToHTML for the exact rules.
|
||||
see https://golang.org/pkg/go/doc/#ToHTML for the exact rules.
|
||||
Godoc also shows example code that is runnable by the testing package;
|
||||
see http://golang.org/pkg/testing/#hdr-Examples for the conventions.
|
||||
see https://golang.org/pkg/testing/#hdr-Examples for the conventions.
|
||||
See "Godoc: documenting Go code" for how to write good comments for godoc:
|
||||
http://golang.org/doc/articles/godoc_documenting_go_code.html
|
||||
https://golang.org/doc/articles/godoc_documenting_go_code.html
|
||||
|
||||
*/
|
||||
package main // import "golang.org/x/tools/cmd/godoc"
|
||||
|
||||
72
vendor/golang.org/x/tools/cmd/godoc/generate-index.bash
generated
vendored
Executable file
72
vendor/golang.org/x/tools/cmd/godoc/generate-index.bash
generated
vendored
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# 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.
|
||||
|
||||
# This script creates a .zip file representing the $GOROOT file system
|
||||
# and computes the corresponding search index files.
|
||||
#
|
||||
# These are used in production (see app.prod.yaml)
|
||||
|
||||
set -e -u -x
|
||||
|
||||
ZIPFILE=godoc.zip
|
||||
INDEXFILE=godoc.index
|
||||
SPLITFILES=index.split.
|
||||
|
||||
error() {
|
||||
echo "error: $1"
|
||||
exit 2
|
||||
}
|
||||
|
||||
install() {
|
||||
go install
|
||||
}
|
||||
|
||||
getArgs() {
|
||||
if [ ! -v GODOC_DOCSET ]; then
|
||||
GODOC_DOCSET="$(go env GOROOT)"
|
||||
echo "GODOC_DOCSET not set explicitly, using GOROOT instead"
|
||||
fi
|
||||
|
||||
# safety checks
|
||||
if [ ! -d "$GODOC_DOCSET" ]; then
|
||||
error "$GODOC_DOCSET is not a directory"
|
||||
fi
|
||||
|
||||
# reporting
|
||||
echo "GODOC_DOCSET = $GODOC_DOCSET"
|
||||
}
|
||||
|
||||
makeZipfile() {
|
||||
echo "*** make $ZIPFILE"
|
||||
rm -f $ZIPFILE goroot
|
||||
ln -s "$GODOC_DOCSET" goroot
|
||||
zip -q -r $ZIPFILE goroot/* # glob to ignore dotfiles (like .git)
|
||||
rm goroot
|
||||
}
|
||||
|
||||
makeIndexfile() {
|
||||
echo "*** make $INDEXFILE"
|
||||
godoc=$(go env GOPATH)/bin/godoc
|
||||
# NOTE: run godoc without GOPATH set. Otherwise third-party packages will end up in the index.
|
||||
GOPATH= $godoc -write_index -goroot goroot -index_files=$INDEXFILE -zip=$ZIPFILE
|
||||
}
|
||||
|
||||
splitIndexfile() {
|
||||
echo "*** split $INDEXFILE"
|
||||
rm -f $SPLITFILES*
|
||||
split -b8m $INDEXFILE $SPLITFILES
|
||||
}
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
install
|
||||
getArgs "$@"
|
||||
makeZipfile
|
||||
makeIndexfile
|
||||
splitIndexfile
|
||||
rm $INDEXFILE
|
||||
|
||||
echo "*** setup complete"
|
||||
9
vendor/golang.org/x/tools/cmd/godoc/godoc19_test.go
generated
vendored
9
vendor/golang.org/x/tools/cmd/godoc/godoc19_test.go
generated
vendored
@@ -1,9 +0,0 @@
|
||||
// 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 main_test
|
||||
|
||||
func init() { isGo19 = true }
|
||||
205
vendor/golang.org/x/tools/cmd/godoc/godoc_test.go
generated
vendored
205
vendor/golang.org/x/tools/cmd/godoc/godoc_test.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
@@ -53,91 +54,6 @@ func buildGodoc(t *testing.T) (bin string, cleanup func()) {
|
||||
return bin, func() { os.RemoveAll(tmp) }
|
||||
}
|
||||
|
||||
var isGo19 bool // godoc19_test.go sets it to true.
|
||||
|
||||
// Basic regression test for godoc command-line tool.
|
||||
func TestCLI(t *testing.T) {
|
||||
bin, cleanup := buildGodoc(t)
|
||||
defer cleanup()
|
||||
|
||||
// condStr returns s if cond is true, otherwise empty string.
|
||||
condStr := func(cond bool, s string) string {
|
||||
if !cond {
|
||||
return ""
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
args []string
|
||||
matches []string // regular expressions
|
||||
dontmatch []string // regular expressions
|
||||
}{
|
||||
{
|
||||
args: []string{"fmt"},
|
||||
matches: []string{
|
||||
`import "fmt"`,
|
||||
`Package fmt implements formatted I/O`,
|
||||
},
|
||||
},
|
||||
{
|
||||
args: []string{"io", "WriteString"},
|
||||
matches: []string{
|
||||
`func WriteString\(`,
|
||||
`WriteString writes the contents of the string s to w`,
|
||||
},
|
||||
},
|
||||
{
|
||||
args: []string{"nonexistingpkg"},
|
||||
matches: []string{
|
||||
`cannot find package` +
|
||||
// TODO: Remove this when support for Go 1.8 is dropped.
|
||||
condStr(!isGo19,
|
||||
// For Go 1.8 and older, because it doesn't have CL 33158 change applied to go/build.
|
||||
// The last pattern (does not e) is for plan9:
|
||||
// http://build.golang.org/log/2d8e5e14ed365bfa434b37ec0338cd9e6f8dd9bf
|
||||
`|no such file or directory|does not exist|cannot find the file|(?:' does not e)`),
|
||||
},
|
||||
},
|
||||
{
|
||||
args: []string{"fmt", "NonexistentSymbol"},
|
||||
matches: []string{
|
||||
`No match found\.`,
|
||||
},
|
||||
},
|
||||
{
|
||||
args: []string{"-src", "syscall", "Open"},
|
||||
matches: []string{
|
||||
`func Open\(`,
|
||||
},
|
||||
dontmatch: []string{
|
||||
`No match found\.`,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
cmd := exec.Command(bin, test.args...)
|
||||
cmd.Args[0] = "godoc"
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Errorf("Running with args %#v: %v", test.args, err)
|
||||
continue
|
||||
}
|
||||
for _, pat := range test.matches {
|
||||
re := regexp.MustCompile(pat)
|
||||
if !re.Match(out) {
|
||||
t.Errorf("godoc %v =\n%s\nwanted /%v/", strings.Join(test.args, " "), out, pat)
|
||||
}
|
||||
}
|
||||
for _, pat := range test.dontmatch {
|
||||
re := regexp.MustCompile(pat)
|
||||
if re.Match(out) {
|
||||
t.Errorf("godoc %v =\n%s\ndid not want /%v/", strings.Join(test.args, " "), out, pat)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func serverAddress(t *testing.T) string {
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
@@ -202,6 +118,17 @@ func waitForServer(t *testing.T, url, match string, timeout time.Duration, rever
|
||||
t.Fatalf("Server failed to respond in %v", timeout)
|
||||
}
|
||||
|
||||
// hasTag checks whether a given release tag is contained in the current version
|
||||
// of the go binary.
|
||||
func hasTag(t string) bool {
|
||||
for _, v := range build.Default.ReleaseTags {
|
||||
if t == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func killAndWait(cmd *exec.Cmd) {
|
||||
cmd.Process.Kill()
|
||||
cmd.Wait()
|
||||
@@ -237,10 +164,14 @@ func testWeb(t *testing.T, withIndex bool) {
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Args[0] = "godoc"
|
||||
|
||||
// Set GOPATH variable to non-existing path.
|
||||
// Set GOPATH variable to non-existing path
|
||||
// and GOPROXY=off to disable module fetches.
|
||||
// We cannot just unset GOPATH variable because godoc would default it to ~/go.
|
||||
// (We don't want the indexer looking at the local workspace during tests.)
|
||||
cmd.Env = append(os.Environ(), "GOPATH=does_not_exist")
|
||||
cmd.Env = append(os.Environ(),
|
||||
"GOPATH=does_not_exist",
|
||||
"GOPROXY=off",
|
||||
"GO111MODULE=off")
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
t.Fatalf("failed to start godoc: %s", err)
|
||||
@@ -255,71 +186,109 @@ func testWeb(t *testing.T, withIndex bool) {
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
path string
|
||||
match []string
|
||||
dontmatch []string
|
||||
needIndex bool
|
||||
path string
|
||||
contains []string // substring
|
||||
match []string // regexp
|
||||
notContains []string
|
||||
needIndex bool
|
||||
releaseTag string // optional release tag that must be in go/build.ReleaseTags
|
||||
}{
|
||||
{
|
||||
path: "/",
|
||||
match: []string{"Go is an open source programming language"},
|
||||
path: "/",
|
||||
contains: []string{"Go is an open source programming language"},
|
||||
},
|
||||
{
|
||||
path: "/pkg/fmt/",
|
||||
match: []string{"Package fmt implements formatted I/O"},
|
||||
path: "/pkg/fmt/",
|
||||
contains: []string{"Package fmt implements formatted I/O"},
|
||||
},
|
||||
{
|
||||
path: "/src/fmt/",
|
||||
match: []string{"scan_test.go"},
|
||||
path: "/src/fmt/",
|
||||
contains: []string{"scan_test.go"},
|
||||
},
|
||||
{
|
||||
path: "/src/fmt/print.go",
|
||||
match: []string{"// Println formats using"},
|
||||
path: "/src/fmt/print.go",
|
||||
contains: []string{"// Println formats using"},
|
||||
},
|
||||
{
|
||||
path: "/pkg",
|
||||
match: []string{
|
||||
contains: []string{
|
||||
"Standard library",
|
||||
"Package fmt implements formatted I/O",
|
||||
},
|
||||
dontmatch: []string{
|
||||
notContains: []string{
|
||||
"internal/syscall",
|
||||
"cmd/gc",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/pkg/?m=all",
|
||||
match: []string{
|
||||
contains: []string{
|
||||
"Standard library",
|
||||
"Package fmt implements formatted I/O",
|
||||
"internal/syscall/?m=all",
|
||||
},
|
||||
dontmatch: []string{
|
||||
notContains: []string{
|
||||
"cmd/gc",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/search?q=ListenAndServe",
|
||||
match: []string{
|
||||
contains: []string{
|
||||
"/src",
|
||||
},
|
||||
dontmatch: []string{
|
||||
notContains: []string{
|
||||
"/pkg/bootstrap",
|
||||
},
|
||||
needIndex: true,
|
||||
},
|
||||
{
|
||||
path: "/pkg/strings/",
|
||||
match: []string{
|
||||
contains: []string{
|
||||
`href="/src/strings/strings.go"`,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/cmd/compile/internal/amd64/",
|
||||
match: []string{
|
||||
contains: []string{
|
||||
`href="/src/cmd/compile/internal/amd64/ssa.go"`,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/pkg/math/bits/",
|
||||
contains: []string{
|
||||
`Added in Go 1.9`,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/pkg/net/",
|
||||
contains: []string{
|
||||
`// IPv6 scoped addressing zone; added in Go 1.1`,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/pkg/net/http/httptrace/",
|
||||
match: []string{
|
||||
`Got1xxResponse.*// Go 1\.11`,
|
||||
},
|
||||
releaseTag: "go1.11",
|
||||
},
|
||||
// Verify we don't add version info to a struct field added the same time
|
||||
// as the struct itself:
|
||||
{
|
||||
path: "/pkg/net/http/httptrace/",
|
||||
match: []string{
|
||||
`(?m)GotFirstResponseByte func\(\)\s*$`,
|
||||
},
|
||||
},
|
||||
// Remove trailing periods before adding semicolons:
|
||||
{
|
||||
path: "/pkg/database/sql/",
|
||||
contains: []string{
|
||||
"The number of connections currently in use; added in Go 1.11",
|
||||
"The number of idle connections; added in Go 1.11",
|
||||
},
|
||||
releaseTag: "go1.11",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
if test.needIndex && !withIndex {
|
||||
@@ -332,18 +301,34 @@ func testWeb(t *testing.T, withIndex bool) {
|
||||
continue
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
strBody := string(body)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
t.Errorf("GET %s: failed to read body: %s (response: %v)", url, err, resp)
|
||||
}
|
||||
isErr := false
|
||||
for _, substr := range test.match {
|
||||
for _, substr := range test.contains {
|
||||
if test.releaseTag != "" && !hasTag(test.releaseTag) {
|
||||
continue
|
||||
}
|
||||
if !bytes.Contains(body, []byte(substr)) {
|
||||
t.Errorf("GET %s: wanted substring %q in body", url, substr)
|
||||
isErr = true
|
||||
}
|
||||
}
|
||||
for _, substr := range test.dontmatch {
|
||||
for _, re := range test.match {
|
||||
if test.releaseTag != "" && !hasTag(test.releaseTag) {
|
||||
continue
|
||||
}
|
||||
if ok, err := regexp.MatchString(re, strBody); !ok || err != nil {
|
||||
if err != nil {
|
||||
t.Fatalf("Bad regexp %q: %v", re, err)
|
||||
}
|
||||
t.Errorf("GET %s: wanted to match %s in body", url, re)
|
||||
isErr = true
|
||||
}
|
||||
}
|
||||
for _, substr := range test.notContains {
|
||||
if bytes.Contains(body, []byte(substr)) {
|
||||
t.Errorf("GET %s: didn't want substring %q in body", url, substr)
|
||||
isErr = true
|
||||
@@ -398,6 +383,8 @@ func main() { print(lib.V) }
|
||||
cmd.Env = os.Environ()
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("GOROOT=%s", filepath.Join(tmpdir, "goroot")))
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("GOPATH=%s", filepath.Join(tmpdir, "gopath")))
|
||||
cmd.Env = append(cmd.Env, "GO111MODULE=off")
|
||||
cmd.Env = append(cmd.Env, "GOPROXY=off")
|
||||
cmd.Stdout = os.Stderr
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
|
||||
56
vendor/golang.org/x/tools/cmd/godoc/handlers.go
generated
vendored
56
vendor/golang.org/x/tools/cmd/godoc/handlers.go
generated
vendored
@@ -21,6 +21,7 @@ import (
|
||||
"text/template"
|
||||
|
||||
"golang.org/x/tools/godoc"
|
||||
"golang.org/x/tools/godoc/env"
|
||||
"golang.org/x/tools/godoc/redirect"
|
||||
"golang.org/x/tools/godoc/vfs"
|
||||
)
|
||||
@@ -30,8 +31,6 @@ var (
|
||||
fs = vfs.NameSpace{}
|
||||
)
|
||||
|
||||
var enforceHosts = false // set true in production on app engine
|
||||
|
||||
// hostEnforcerHandler redirects requests to "http://foo.golang.org/bar"
|
||||
// to "https://golang.org/bar".
|
||||
// It permits requests to the host "godoc-test.golang.org" for testing and
|
||||
@@ -41,11 +40,11 @@ type hostEnforcerHandler struct {
|
||||
}
|
||||
|
||||
func (h hostEnforcerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if !enforceHosts {
|
||||
if !env.EnforceHosts() {
|
||||
h.h.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
if r.TLS == nil || !h.validHost(r.Host) {
|
||||
if !h.isHTTPS(r) || !h.validHost(r.Host) {
|
||||
r.URL.Scheme = "https"
|
||||
if h.validHost(r.Host) {
|
||||
r.URL.Host = r.Host
|
||||
@@ -59,9 +58,17 @@ func (h hostEnforcerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
h.h.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func (h hostEnforcerHandler) isHTTPS(r *http.Request) bool {
|
||||
return r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https"
|
||||
}
|
||||
|
||||
func (h hostEnforcerHandler) validHost(host string) bool {
|
||||
switch strings.ToLower(host) {
|
||||
case "golang.org", "godoc-test.golang.org", "golang.google.cn":
|
||||
case "golang.org", "golang.google.cn":
|
||||
return true
|
||||
}
|
||||
if strings.HasSuffix(host, "-dot-golang-org.appspot.com") {
|
||||
// staging/test
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -105,28 +112,23 @@ func readTemplate(name string) *template.Template {
|
||||
return t
|
||||
}
|
||||
|
||||
func readTemplates(p *godoc.Presentation, html bool) {
|
||||
p.PackageText = readTemplate("package.txt")
|
||||
p.SearchText = readTemplate("search.txt")
|
||||
|
||||
if html || p.HTMLMode {
|
||||
codewalkHTML = readTemplate("codewalk.html")
|
||||
codewalkdirHTML = readTemplate("codewalkdir.html")
|
||||
p.CallGraphHTML = readTemplate("callgraph.html")
|
||||
p.DirlistHTML = readTemplate("dirlist.html")
|
||||
p.ErrorHTML = readTemplate("error.html")
|
||||
p.ExampleHTML = readTemplate("example.html")
|
||||
p.GodocHTML = readTemplate("godoc.html")
|
||||
p.ImplementsHTML = readTemplate("implements.html")
|
||||
p.MethodSetHTML = readTemplate("methodset.html")
|
||||
p.PackageHTML = readTemplate("package.html")
|
||||
p.PackageRootHTML = readTemplate("packageroot.html")
|
||||
p.SearchHTML = readTemplate("search.html")
|
||||
p.SearchDocHTML = readTemplate("searchdoc.html")
|
||||
p.SearchCodeHTML = readTemplate("searchcode.html")
|
||||
p.SearchTxtHTML = readTemplate("searchtxt.html")
|
||||
p.SearchDescXML = readTemplate("opensearch.xml")
|
||||
}
|
||||
func readTemplates(p *godoc.Presentation) {
|
||||
codewalkHTML = readTemplate("codewalk.html")
|
||||
codewalkdirHTML = readTemplate("codewalkdir.html")
|
||||
p.CallGraphHTML = readTemplate("callgraph.html")
|
||||
p.DirlistHTML = readTemplate("dirlist.html")
|
||||
p.ErrorHTML = readTemplate("error.html")
|
||||
p.ExampleHTML = readTemplate("example.html")
|
||||
p.GodocHTML = readTemplate("godoc.html")
|
||||
p.ImplementsHTML = readTemplate("implements.html")
|
||||
p.MethodSetHTML = readTemplate("methodset.html")
|
||||
p.PackageHTML = readTemplate("package.html")
|
||||
p.PackageRootHTML = readTemplate("packageroot.html")
|
||||
p.SearchHTML = readTemplate("search.html")
|
||||
p.SearchDocHTML = readTemplate("searchdoc.html")
|
||||
p.SearchCodeHTML = readTemplate("searchcode.html")
|
||||
p.SearchTxtHTML = readTemplate("searchtxt.html")
|
||||
p.SearchDescXML = readTemplate("opensearch.xml")
|
||||
}
|
||||
|
||||
type fmtResponse struct {
|
||||
|
||||
BIN
vendor/golang.org/x/tools/cmd/godoc/hg-git-mapping.bin
generated
vendored
Normal file
BIN
vendor/golang.org/x/tools/cmd/godoc/hg-git-mapping.bin
generated
vendored
Normal file
Binary file not shown.
185
vendor/golang.org/x/tools/cmd/godoc/main.go
generated
vendored
185
vendor/golang.org/x/tools/cmd/godoc/main.go
generated
vendored
@@ -14,28 +14,20 @@
|
||||
// (idea is if you say import "compress/zlib", you go to
|
||||
// http://godoc/pkg/compress/zlib)
|
||||
//
|
||||
// Command-line interface:
|
||||
//
|
||||
// godoc packagepath [name ...]
|
||||
//
|
||||
// godoc compress/zlib
|
||||
// - prints doc for package compress/zlib
|
||||
// godoc crypto/block Cipher NewCMAC
|
||||
// - prints doc for Cipher and NewCMAC in package crypto/block
|
||||
|
||||
// +build !appengine
|
||||
// +build !golangorg
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
_ "expvar" // to serve /debug/vars
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
_ "net/http/pprof" // to serve /debug/pprof/*
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -53,7 +45,7 @@ import (
|
||||
"golang.org/x/tools/godoc/vfs/zipfs"
|
||||
)
|
||||
|
||||
const defaultAddr = ":6060" // default webserver address
|
||||
const defaultAddr = "localhost:6060" // default webserver address
|
||||
|
||||
var (
|
||||
// file system to serve
|
||||
@@ -66,18 +58,11 @@ var (
|
||||
analysisFlag = flag.String("analysis", "", `comma-separated list of analyses to perform (supported: type, pointer). See http://golang.org/lib/godoc/analysis/help.html`)
|
||||
|
||||
// network
|
||||
httpAddr = flag.String("http", "", "HTTP service address (e.g., '"+defaultAddr+"')")
|
||||
serverAddr = flag.String("server", "", "webserver address for command line searches")
|
||||
httpAddr = flag.String("http", defaultAddr, "HTTP service address")
|
||||
|
||||
// layout control
|
||||
html = flag.Bool("html", false, "print HTML in command-line mode")
|
||||
srcMode = flag.Bool("src", false, "print (exported) source in command-line mode")
|
||||
allMode = flag.Bool("all", false, "include unexported identifiers in command-line mode")
|
||||
urlFlag = flag.String("url", "", "print HTML for named URL")
|
||||
|
||||
// command-line searches
|
||||
query = flag.Bool("q", false, "arguments are considered search queries")
|
||||
|
||||
verbose = flag.Bool("v", false, "verbose mode")
|
||||
|
||||
// file system roots
|
||||
@@ -85,11 +70,9 @@ var (
|
||||
goroot = flag.String("goroot", findGOROOT(), "Go root directory")
|
||||
|
||||
// layout control
|
||||
tabWidth = flag.Int("tabwidth", 4, "tab width")
|
||||
showTimestamps = flag.Bool("timestamps", false, "show timestamps with directory listings")
|
||||
templateDir = flag.String("templates", "", "load templates/JS/CSS from disk in this directory")
|
||||
showPlayground = flag.Bool("play", false, "enable playground in web interface")
|
||||
showExamples = flag.Bool("ex", false, "show examples in command line mode")
|
||||
showPlayground = flag.Bool("play", false, "enable playground")
|
||||
declLinks = flag.Bool("links", true, "link identifiers to their declarations")
|
||||
|
||||
// search index
|
||||
@@ -103,10 +86,19 @@ var (
|
||||
notesRx = flag.String("notes", "BUG", "regular expression matching note markers to show")
|
||||
)
|
||||
|
||||
// An httpResponseRecorder is an http.ResponseWriter
|
||||
type httpResponseRecorder struct {
|
||||
body *bytes.Buffer
|
||||
header http.Header
|
||||
code int
|
||||
}
|
||||
|
||||
func (w *httpResponseRecorder) Header() http.Header { return w.header }
|
||||
func (w *httpResponseRecorder) Write(b []byte) (int, error) { return len(b), nil }
|
||||
func (w *httpResponseRecorder) WriteHeader(code int) { w.code = code }
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr,
|
||||
"usage: godoc package [name ...]\n"+
|
||||
" godoc -http="+defaultAddr+"\n")
|
||||
fmt.Fprintf(os.Stderr, "usage: godoc -http="+defaultAddr+"\n")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(2)
|
||||
}
|
||||
@@ -133,22 +125,22 @@ func handleURLFlag() {
|
||||
|
||||
// Invoke default HTTP handler to serve request
|
||||
// to our buffering httpWriter.
|
||||
w := httptest.NewRecorder()
|
||||
w := &httpResponseRecorder{code: 200, header: make(http.Header), body: new(bytes.Buffer)}
|
||||
http.DefaultServeMux.ServeHTTP(w, req)
|
||||
|
||||
// Return data, error, or follow redirect.
|
||||
switch w.Code {
|
||||
switch w.code {
|
||||
case 200: // ok
|
||||
os.Stdout.Write(w.Body.Bytes())
|
||||
os.Stdout.Write(w.body.Bytes())
|
||||
return
|
||||
case 301, 302, 303, 307: // redirect
|
||||
redirect := w.HeaderMap.Get("Location")
|
||||
redirect := w.header.Get("Location")
|
||||
if redirect == "" {
|
||||
log.Fatalf("HTTP %d without Location header", w.Code)
|
||||
log.Fatalf("HTTP %d without Location header", w.code)
|
||||
}
|
||||
urlstr = redirect
|
||||
default:
|
||||
log.Fatalf("HTTP error %d", w.Code)
|
||||
log.Fatalf("HTTP error %d", w.code)
|
||||
}
|
||||
}
|
||||
log.Fatalf("too many redirects")
|
||||
@@ -173,7 +165,7 @@ func main() {
|
||||
|
||||
// Check usage: server and no args.
|
||||
if (*httpAddr != "" || *urlFlag != "") && (flag.NArg() > 0) {
|
||||
fmt.Fprintln(os.Stderr, "can't use -http with args.")
|
||||
fmt.Fprintln(os.Stderr, "Unexpected arguments.")
|
||||
usage()
|
||||
}
|
||||
|
||||
@@ -183,8 +175,10 @@ func main() {
|
||||
usage()
|
||||
}
|
||||
|
||||
var fsGate chan bool
|
||||
fsGate = make(chan bool, 20)
|
||||
// Set the resolved goroot.
|
||||
vfs.GOROOT = *goroot
|
||||
|
||||
fsGate := make(chan bool, 20)
|
||||
|
||||
// Determine file system to use.
|
||||
if *zipfile == "" {
|
||||
@@ -211,8 +205,6 @@ func main() {
|
||||
fs.Bind("/src", gatefs.New(vfs.OS(p), fsGate), "/src", vfs.BindAfter)
|
||||
}
|
||||
|
||||
httpMode := *httpAddr != ""
|
||||
|
||||
var typeAnalysis, pointerAnalysis bool
|
||||
if *analysisFlag != "" {
|
||||
for _, a := range strings.Split(*analysisFlag, ",") {
|
||||
@@ -230,7 +222,7 @@ func main() {
|
||||
corpus := godoc.NewCorpus(fs)
|
||||
corpus.Verbose = *verbose
|
||||
corpus.MaxResults = *maxResults
|
||||
corpus.IndexEnabled = *indexEnabled && httpMode
|
||||
corpus.IndexEnabled = *indexEnabled
|
||||
if *maxResults == 0 {
|
||||
corpus.IndexFullText = false
|
||||
}
|
||||
@@ -241,29 +233,24 @@ func main() {
|
||||
if *writeIndex {
|
||||
corpus.IndexThrottle = 1.0
|
||||
corpus.IndexEnabled = true
|
||||
}
|
||||
if *writeIndex || httpMode || *urlFlag != "" {
|
||||
if httpMode {
|
||||
go initCorpus(corpus)
|
||||
} else {
|
||||
initCorpus(corpus)
|
||||
}
|
||||
initCorpus(corpus)
|
||||
} else {
|
||||
go initCorpus(corpus)
|
||||
}
|
||||
|
||||
// Initialize the version info before readTemplates, which saves
|
||||
// the map value in a method value.
|
||||
corpus.InitVersionInfo()
|
||||
|
||||
pres = godoc.NewPresentation(corpus)
|
||||
pres.TabWidth = *tabWidth
|
||||
pres.ShowTimestamps = *showTimestamps
|
||||
pres.ShowPlayground = *showPlayground
|
||||
pres.ShowExamples = *showExamples
|
||||
pres.DeclLinks = *declLinks
|
||||
pres.SrcMode = *srcMode
|
||||
pres.HTMLMode = *html
|
||||
pres.AllMode = *allMode
|
||||
if *notesRx != "" {
|
||||
pres.NotesRx = regexp.MustCompile(*notesRx)
|
||||
}
|
||||
|
||||
readTemplates(pres, httpMode || *urlFlag != "")
|
||||
readTemplates(pres)
|
||||
registerHandlers(pres)
|
||||
|
||||
if *writeIndex {
|
||||
@@ -298,67 +285,51 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
if httpMode {
|
||||
// HTTP server mode.
|
||||
var handler http.Handler = http.DefaultServeMux
|
||||
if *verbose {
|
||||
log.Printf("Go Documentation Server")
|
||||
log.Printf("version = %s", runtime.Version())
|
||||
log.Printf("address = %s", *httpAddr)
|
||||
log.Printf("goroot = %s", *goroot)
|
||||
log.Printf("tabwidth = %d", *tabWidth)
|
||||
switch {
|
||||
case !*indexEnabled:
|
||||
log.Print("search index disabled")
|
||||
case *maxResults > 0:
|
||||
log.Printf("full text index enabled (maxresults = %d)", *maxResults)
|
||||
default:
|
||||
log.Print("identifier search index enabled")
|
||||
var handler http.Handler = http.DefaultServeMux
|
||||
if *verbose {
|
||||
log.Printf("Go Documentation Server")
|
||||
log.Printf("version = %s", runtime.Version())
|
||||
log.Printf("address = %s", *httpAddr)
|
||||
log.Printf("goroot = %s", *goroot)
|
||||
switch {
|
||||
case !*indexEnabled:
|
||||
log.Print("search index disabled")
|
||||
case *maxResults > 0:
|
||||
log.Printf("full text index enabled (maxresults = %d)", *maxResults)
|
||||
default:
|
||||
log.Print("identifier search index enabled")
|
||||
}
|
||||
fs.Fprint(os.Stderr)
|
||||
handler = loggingHandler(handler)
|
||||
}
|
||||
|
||||
// Initialize search index.
|
||||
if *indexEnabled {
|
||||
go corpus.RunIndexer()
|
||||
}
|
||||
|
||||
// Start type/pointer analysis.
|
||||
if typeAnalysis || pointerAnalysis {
|
||||
go analysis.Run(pointerAnalysis, &corpus.Analysis)
|
||||
}
|
||||
|
||||
if runHTTPS != nil {
|
||||
go func() {
|
||||
if err := runHTTPS(handler); err != nil {
|
||||
log.Fatalf("ListenAndServe TLS: %v", err)
|
||||
}
|
||||
fs.Fprint(os.Stderr)
|
||||
handler = loggingHandler(handler)
|
||||
}
|
||||
|
||||
// Initialize search index.
|
||||
if *indexEnabled {
|
||||
go corpus.RunIndexer()
|
||||
}
|
||||
|
||||
// Start type/pointer analysis.
|
||||
if typeAnalysis || pointerAnalysis {
|
||||
go analysis.Run(pointerAnalysis, &corpus.Analysis)
|
||||
}
|
||||
|
||||
if runHTTPS != nil {
|
||||
go func() {
|
||||
if err := runHTTPS(handler); err != nil {
|
||||
log.Fatalf("ListenAndServe TLS: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Start http server.
|
||||
if *verbose {
|
||||
log.Println("starting HTTP server")
|
||||
}
|
||||
if wrapHTTPMux != nil {
|
||||
handler = wrapHTTPMux(handler)
|
||||
}
|
||||
if err := http.ListenAndServe(*httpAddr, handler); err != nil {
|
||||
log.Fatalf("ListenAndServe %s: %v", *httpAddr, err)
|
||||
}
|
||||
|
||||
return
|
||||
}()
|
||||
}
|
||||
|
||||
if *query {
|
||||
handleRemoteSearch()
|
||||
return
|
||||
// Start http server.
|
||||
if *verbose {
|
||||
log.Println("starting HTTP server")
|
||||
}
|
||||
|
||||
build.Default.GOROOT = *goroot
|
||||
if err := godoc.CommandLine(os.Stdout, fs, pres, flag.Args()); err != nil {
|
||||
log.Print(err)
|
||||
if wrapHTTPMux != nil {
|
||||
handler = wrapHTTPMux(handler)
|
||||
}
|
||||
if err := http.ListenAndServe(*httpAddr, handler); err != nil {
|
||||
log.Fatalf("ListenAndServe %s: %v", *httpAddr, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
vendor/golang.org/x/tools/cmd/godoc/play.go
generated
vendored
2
vendor/golang.org/x/tools/cmd/godoc/play.go
generated
vendored
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !appengine
|
||||
// +build !golangorg
|
||||
|
||||
package main
|
||||
|
||||
|
||||
155
vendor/golang.org/x/tools/cmd/godoc/regtest_test.go
generated
vendored
Normal file
155
vendor/golang.org/x/tools/cmd/godoc/regtest_test.go
generated
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// Regression tests to run against a production instance of godoc.
|
||||
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var host = flag.String("regtest.host", "", "host to run regression test against")
|
||||
|
||||
func init() {
|
||||
flag.Parse()
|
||||
*host = strings.TrimSuffix(*host, "/")
|
||||
}
|
||||
|
||||
func TestLiveServer(t *testing.T) {
|
||||
if *host == "" {
|
||||
t.Skip("regtest.host flag missing.")
|
||||
}
|
||||
substringTests := []struct {
|
||||
Message string
|
||||
Path string
|
||||
Substring string
|
||||
Regexp string
|
||||
NoAnalytics bool // expect the response to not contain GA.
|
||||
PostBody string
|
||||
}{
|
||||
{
|
||||
Path: "/doc/faq",
|
||||
Substring: "What is the purpose of the project",
|
||||
},
|
||||
{
|
||||
Path: "/pkg/",
|
||||
Substring: "Package tar",
|
||||
},
|
||||
{
|
||||
Path: "/pkg/os/",
|
||||
Substring: "func Open",
|
||||
},
|
||||
{
|
||||
Path: "/pkg/net/http/",
|
||||
Substring: `title="Added in Go 1.11"`,
|
||||
Message: "version information not present - failed InitVersionInfo?",
|
||||
},
|
||||
{
|
||||
Path: "/robots.txt",
|
||||
Substring: "Disallow: /search",
|
||||
Message: "robots not present - not deployed from Dockerfile?",
|
||||
NoAnalytics: true,
|
||||
},
|
||||
{
|
||||
Path: "/change/75944e2e3a63",
|
||||
Substring: "bdb10cf",
|
||||
Message: "no change redirect - hg to git mapping not registered?",
|
||||
NoAnalytics: true,
|
||||
},
|
||||
{
|
||||
Path: "/dl/",
|
||||
Substring: "go1.11.windows-amd64.msi",
|
||||
Message: "missing data on dl page - misconfiguration of datastore?",
|
||||
},
|
||||
{
|
||||
Path: "/dl/?mode=json",
|
||||
Substring: ".windows-amd64.msi",
|
||||
NoAnalytics: true,
|
||||
},
|
||||
{
|
||||
Message: "broken shortlinks - misconfiguration of datastore or memcache?",
|
||||
Path: "/s/go2design",
|
||||
Regexp: "proposal.*Found",
|
||||
NoAnalytics: true,
|
||||
},
|
||||
{
|
||||
Message: "incorrect search result - broken index?",
|
||||
Path: "/search?q=IsDir",
|
||||
Substring: "src/os/types.go",
|
||||
},
|
||||
{
|
||||
Path: "/compile",
|
||||
PostBody: "body=" + url.QueryEscape("package main; func main() { print(6*7); }"),
|
||||
Regexp: `^{"compile_errors":"","output":"42"}$`,
|
||||
NoAnalytics: true,
|
||||
},
|
||||
{
|
||||
Path: "/compile",
|
||||
PostBody: "body=" + url.QueryEscape("//empty"),
|
||||
Substring: "expected 'package', found 'EOF'",
|
||||
NoAnalytics: true,
|
||||
},
|
||||
{
|
||||
Path: "/compile",
|
||||
PostBody: "version=2&body=package+main%3Bimport+(%22fmt%22%3B%22time%22)%3Bfunc+main()%7Bfmt.Print(%22A%22)%3Btime.Sleep(time.Second)%3Bfmt.Print(%22B%22)%7D",
|
||||
Regexp: `^{"Errors":"","Events":\[{"Message":"A","Kind":"stdout","Delay":0},{"Message":"B","Kind":"stdout","Delay":1000000000}\]}$`,
|
||||
NoAnalytics: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range substringTests {
|
||||
t.Run(tc.Path, func(t *testing.T) {
|
||||
method := "GET"
|
||||
var reqBody io.Reader
|
||||
if tc.PostBody != "" {
|
||||
method = "POST"
|
||||
reqBody = strings.NewReader(tc.PostBody)
|
||||
}
|
||||
req, err := http.NewRequest(method, *host+tc.Path, reqBody)
|
||||
if err != nil {
|
||||
t.Fatalf("NewRequest: %v", err)
|
||||
}
|
||||
if reqBody != nil {
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
}
|
||||
resp, err := http.DefaultTransport.RoundTrip(req)
|
||||
if err != nil {
|
||||
t.Fatalf("RoundTrip: %v", err)
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadAll: %v", err)
|
||||
}
|
||||
|
||||
const googleAnalyticsID = "UA-11222381-2" // golang.org analytics ID
|
||||
if !tc.NoAnalytics && !bytes.Contains(body, []byte(googleAnalyticsID)) {
|
||||
t.Errorf("want response to contain analytics tracking ID")
|
||||
}
|
||||
|
||||
if tc.Substring != "" {
|
||||
tc.Regexp = regexp.QuoteMeta(tc.Substring)
|
||||
}
|
||||
re := regexp.MustCompile(tc.Regexp)
|
||||
|
||||
if !re.Match(body) {
|
||||
t.Log("------ actual output -------")
|
||||
t.Log(string(body))
|
||||
t.Log("----------------------------")
|
||||
if tc.Message != "" {
|
||||
t.Log(tc.Message)
|
||||
}
|
||||
t.Fatalf("wanted response to match %s", tc.Regexp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
72
vendor/golang.org/x/tools/cmd/godoc/remotesearch.go
generated
vendored
72
vendor/golang.org/x/tools/cmd/godoc/remotesearch.go
generated
vendored
@@ -1,72 +0,0 @@
|
||||
// Copyright 2009 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 !appengine
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
)
|
||||
|
||||
func handleRemoteSearch() {
|
||||
// Command-line queries.
|
||||
for i := 0; i < flag.NArg(); i++ {
|
||||
res, err := remoteSearch(flag.Arg(i))
|
||||
if err != nil {
|
||||
log.Fatalf("remoteSearch: %s", err)
|
||||
}
|
||||
io.Copy(os.Stdout, res.Body)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// remoteSearchURL returns the search URL for a given query as needed by
|
||||
// remoteSearch. If html is set, an html result is requested; otherwise
|
||||
// the result is in textual form.
|
||||
// Adjust this function as necessary if modeNames or FormValue parameters
|
||||
// change.
|
||||
func remoteSearchURL(query string, html bool) string {
|
||||
s := "/search?m=text&q="
|
||||
if html {
|
||||
s = "/search?q="
|
||||
}
|
||||
return s + url.QueryEscape(query)
|
||||
}
|
||||
|
||||
func remoteSearch(query string) (res *http.Response, err error) {
|
||||
// list of addresses to try
|
||||
var addrs []string
|
||||
if *serverAddr != "" {
|
||||
// explicit server address - only try this one
|
||||
addrs = []string{*serverAddr}
|
||||
} else {
|
||||
addrs = []string{
|
||||
defaultAddr,
|
||||
"golang.org",
|
||||
}
|
||||
}
|
||||
|
||||
// remote search
|
||||
search := remoteSearchURL(query, *html)
|
||||
for _, addr := range addrs {
|
||||
url := "http://" + addr + search
|
||||
res, err = http.Get(url)
|
||||
if err == nil && res.StatusCode == http.StatusOK {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil && res.StatusCode != http.StatusOK {
|
||||
err = errors.New(res.Status)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
134
vendor/golang.org/x/tools/cmd/godoc/setup-godoc-app.bash
generated
vendored
134
vendor/golang.org/x/tools/cmd/godoc/setup-godoc-app.bash
generated
vendored
@@ -1,134 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# 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.
|
||||
|
||||
# This script creates a complete godoc app in $APPDIR.
|
||||
# It copies the cmd/godoc and src/go/... sources from GOROOT,
|
||||
# synthesizes an app.yaml file, and creates the .zip, index, and
|
||||
# configuration files.
|
||||
#
|
||||
# If an argument is provided it is assumed to be the app-engine godoc directory.
|
||||
# Without an argument, $APPDIR is used instead. If GOROOT is not set, "go env"
|
||||
# is consulted to find the $GOROOT.
|
||||
#
|
||||
# The script creates a .zip file representing the $GOROOT file system
|
||||
# and computes the correspondig search index files. These files are then
|
||||
# copied to $APPDIR. A corresponding godoc configuration file is created
|
||||
# in $APPDIR/appconfig.go.
|
||||
|
||||
ZIPFILE=godoc.zip
|
||||
INDEXFILE=godoc.index
|
||||
SPLITFILES=index.split.
|
||||
GODOC=golang.org/x/tools/cmd/godoc
|
||||
CONFIGFILE=$GODOC/appconfig.go
|
||||
|
||||
error() {
|
||||
echo "error: $1"
|
||||
exit 2
|
||||
}
|
||||
|
||||
getArgs() {
|
||||
if [ -z $APPENGINE_SDK ]; then
|
||||
error "APPENGINE_SDK environment variable not set"
|
||||
fi
|
||||
if [ ! -x $APPENGINE_SDK/goapp ]; then
|
||||
error "couldn't find goapp command in $APPENGINE_SDK"
|
||||
fi
|
||||
if [ -z $GOROOT ]; then
|
||||
GOROOT=$(go env GOROOT)
|
||||
echo "GOROOT not set explicitly, using go env value instead"
|
||||
fi
|
||||
if [ -z $APPDIR ]; then
|
||||
if [ $# == 0 ]; then
|
||||
error "APPDIR not set, and no argument provided"
|
||||
fi
|
||||
APPDIR=$1
|
||||
echo "APPDIR not set, using argument instead"
|
||||
fi
|
||||
|
||||
# safety checks
|
||||
if [ ! -d $GOROOT ]; then
|
||||
error "$GOROOT is not a directory"
|
||||
fi
|
||||
if [ -e $APPDIR ]; then
|
||||
error "$APPDIR exists; check and remove it before trying again"
|
||||
fi
|
||||
|
||||
# reporting
|
||||
echo "GOROOT = $GOROOT"
|
||||
echo "APPDIR = $APPDIR"
|
||||
}
|
||||
|
||||
fetchGodoc() {
|
||||
echo "*** Fetching godoc (if not already in GOPATH)"
|
||||
unset GOBIN
|
||||
go=$APPENGINE_SDK/goapp
|
||||
$go get -d -tags appengine $GODOC
|
||||
mkdir -p $APPDIR/$GODOC
|
||||
cp $(find $($go list -f '{{.Dir}}' $GODOC) -mindepth 1 -maxdepth 1 -type f) $APPDIR/$GODOC/
|
||||
}
|
||||
|
||||
makeAppYaml() {
|
||||
echo "*** make $APPDIR/app.yaml"
|
||||
cat > $APPDIR/app.yaml <<EOF
|
||||
application: godoc
|
||||
version: 1
|
||||
runtime: go
|
||||
api_version: go1
|
||||
|
||||
handlers:
|
||||
- url: /.*
|
||||
script: _go_app
|
||||
EOF
|
||||
}
|
||||
|
||||
makeZipfile() {
|
||||
echo "*** make $APPDIR/$ZIPFILE"
|
||||
zip -q -r $APPDIR/$ZIPFILE $GOROOT/*
|
||||
}
|
||||
|
||||
makeIndexfile() {
|
||||
echo "*** make $APPDIR/$INDEXFILE"
|
||||
GOPATH= godoc -write_index -index_files=$APPDIR/$INDEXFILE -zip=$APPDIR/$ZIPFILE
|
||||
}
|
||||
|
||||
splitIndexfile() {
|
||||
echo "*** split $APPDIR/$INDEXFILE"
|
||||
split -b8m $APPDIR/$INDEXFILE $APPDIR/$SPLITFILES
|
||||
}
|
||||
|
||||
makeConfigfile() {
|
||||
echo "*** make $APPDIR/$CONFIGFILE"
|
||||
cat > $APPDIR/$CONFIGFILE <<EOF
|
||||
package main
|
||||
|
||||
// GENERATED FILE - DO NOT MODIFY BY HAND.
|
||||
// (generated by golang.org/x/tools/cmd/godoc/setup-godoc-app.bash)
|
||||
|
||||
const (
|
||||
// .zip filename
|
||||
zipFilename = "$ZIPFILE"
|
||||
|
||||
// goroot directory in .zip file
|
||||
zipGoroot = "$GOROOT"
|
||||
|
||||
// glob pattern describing search index files
|
||||
// (if empty, the index is built at run-time)
|
||||
indexFilenames = "$SPLITFILES*"
|
||||
)
|
||||
EOF
|
||||
}
|
||||
|
||||
getArgs "$@"
|
||||
set -e
|
||||
mkdir $APPDIR
|
||||
fetchGodoc
|
||||
makeAppYaml
|
||||
makeZipfile
|
||||
makeIndexfile
|
||||
splitIndexfile
|
||||
makeConfigfile
|
||||
|
||||
echo "*** setup complete"
|
||||
147
vendor/golang.org/x/tools/cmd/golsp/main.go
generated
vendored
Normal file
147
vendor/golang.org/x/tools/cmd/golsp/main.go
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// The golsp command is an LSP server for Go.
|
||||
// The Language Server Protocol allows any text editor
|
||||
// to be extended with IDE-like features;
|
||||
// see https://langserver.org/ for details.
|
||||
package main // import "golang.org/x/tools/cmd/golsp"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"runtime/trace"
|
||||
"time"
|
||||
|
||||
"golang.org/x/tools/internal/jsonrpc2"
|
||||
"golang.org/x/tools/internal/lsp"
|
||||
)
|
||||
|
||||
var (
|
||||
cpuprofile = flag.String("cpuprofile", "", "write CPU profile to this file")
|
||||
memprofile = flag.String("memprofile", "", "write memory profile to this file")
|
||||
traceFlag = flag.String("trace", "", "write trace log to this file")
|
||||
|
||||
// Flags for compatitibility with VSCode.
|
||||
logfile = flag.String("logfile", "", "filename to log to")
|
||||
mode = flag.String("mode", "", "no effect")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "usage: golsp [flags]\n")
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
flag.Parse()
|
||||
if flag.NArg() > 0 {
|
||||
flag.Usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if *cpuprofile != "" {
|
||||
f, err := os.Create(*cpuprofile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := pprof.StartCPUProfile(f); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// NB: profile won't be written in case of error.
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
if *traceFlag != "" {
|
||||
f, err := os.Create(*traceFlag)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := trace.Start(f); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// NB: trace log won't be written in case of error.
|
||||
defer func() {
|
||||
trace.Stop()
|
||||
log.Printf("To view the trace, run:\n$ go tool trace view %s", *traceFlag)
|
||||
}()
|
||||
}
|
||||
|
||||
if *memprofile != "" {
|
||||
f, err := os.Create(*memprofile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// NB: memprofile won't be written in case of error.
|
||||
defer func() {
|
||||
runtime.GC() // get up-to-date statistics
|
||||
if err := pprof.WriteHeapProfile(f); err != nil {
|
||||
log.Fatalf("Writing memory profile: %v", err)
|
||||
}
|
||||
f.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
out := os.Stderr
|
||||
if *logfile != "" {
|
||||
f, err := os.Create(*logfile)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to create log file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
log.SetOutput(io.MultiWriter(os.Stderr, f))
|
||||
out = f
|
||||
}
|
||||
if err := lsp.RunServer(
|
||||
context.Background(),
|
||||
jsonrpc2.NewHeaderStream(os.Stdin, os.Stdout),
|
||||
func(direction jsonrpc2.Direction, id *jsonrpc2.ID, elapsed time.Duration, method string, payload *json.RawMessage, err *jsonrpc2.Error) {
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(out, "[Error - %v] %s %s%s %v", time.Now().Format("3:04:05 PM"), direction, method, id, err)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(out, "[Trace - %v] ", time.Now().Format("3:04:05 PM"))
|
||||
switch direction {
|
||||
case jsonrpc2.Send:
|
||||
fmt.Fprint(out, "Received ")
|
||||
case jsonrpc2.Receive:
|
||||
fmt.Fprint(out, "Sending ")
|
||||
}
|
||||
switch {
|
||||
case id == nil:
|
||||
fmt.Fprint(out, "notification ")
|
||||
case elapsed >= 0:
|
||||
fmt.Fprint(out, "response ")
|
||||
default:
|
||||
fmt.Fprint(out, "request ")
|
||||
}
|
||||
fmt.Fprintf(out, "'%s", method)
|
||||
switch {
|
||||
case id == nil:
|
||||
// do nothing
|
||||
case id.Name != "":
|
||||
fmt.Fprintf(out, " - (%s)", id.Name)
|
||||
default:
|
||||
fmt.Fprintf(out, " - (%d)", id.Number)
|
||||
}
|
||||
fmt.Fprint(out, "'")
|
||||
if elapsed >= 0 {
|
||||
fmt.Fprintf(out, " in %vms", elapsed.Nanoseconds()/1000)
|
||||
}
|
||||
params := string(*payload)
|
||||
if params == "null" {
|
||||
params = "{}"
|
||||
}
|
||||
fmt.Fprintf(out, ".\r\nParams: %s\r\n\r\n\r\n", params)
|
||||
},
|
||||
); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
2
vendor/golang.org/x/tools/cmd/gorename/gorename_test.go
generated
vendored
2
vendor/golang.org/x/tools/cmd/gorename/gorename_test.go
generated
vendored
@@ -48,6 +48,8 @@ func TestGeneratedFiles(t *testing.T) {
|
||||
env = append(env, envVar)
|
||||
}
|
||||
}
|
||||
// gorename currently requires GOPATH mode.
|
||||
env = append(env, "GO111MODULE=off")
|
||||
|
||||
// Testing renaming in packages that include cgo files:
|
||||
for iter, renameTest := range []test{
|
||||
|
||||
4
vendor/golang.org/x/tools/cmd/goyacc/yacc.go
generated
vendored
4
vendor/golang.org/x/tools/cmd/goyacc/yacc.go
generated
vendored
@@ -387,7 +387,7 @@ func setup() {
|
||||
yaccpar = strings.Replace(yaccpartext, "$$", prefix, -1)
|
||||
openup()
|
||||
|
||||
fmt.Fprintf(ftable, "// Code generated by goyacc %s. DO NOT EDIT.", strings.Join(os.Args[1:], " "))
|
||||
fmt.Fprintf(ftable, "// Code generated by goyacc %s. DO NOT EDIT.\n", strings.Join(os.Args[1:], " "))
|
||||
|
||||
defin(0, "$end")
|
||||
extval = PRIVATE // tokens start in unicode 'private use'
|
||||
@@ -1272,7 +1272,7 @@ l1:
|
||||
func cpyact(curprod []int, max int) {
|
||||
|
||||
if !lflag {
|
||||
fmt.Fprintf(fcode, "\n\t\t//line %v:%v", infile, lineno)
|
||||
fmt.Fprintf(fcode, "\n//line %v:%v", infile, lineno)
|
||||
}
|
||||
fmt.Fprint(fcode, "\n\t\t")
|
||||
|
||||
|
||||
2
vendor/golang.org/x/tools/cmd/guru/callees.go
generated
vendored
2
vendor/golang.org/x/tools/cmd/guru/callees.go
generated
vendored
@@ -18,7 +18,7 @@ import (
|
||||
"golang.org/x/tools/go/ssa/ssautil"
|
||||
)
|
||||
|
||||
// Callees reports the possible callees of the function call site
|
||||
// The callees function reports the possible callees of the function call site
|
||||
// identified by the specified source location.
|
||||
func callees(q *Query) error {
|
||||
lconf := loader.Config{Build: q.Build}
|
||||
|
||||
2
vendor/golang.org/x/tools/cmd/guru/callers.go
generated
vendored
2
vendor/golang.org/x/tools/cmd/guru/callers.go
generated
vendored
@@ -16,7 +16,7 @@ import (
|
||||
"golang.org/x/tools/go/ssa/ssautil"
|
||||
)
|
||||
|
||||
// Callers reports the possible callers of the function
|
||||
// The callers function reports the possible callers of the function
|
||||
// immediately enclosing the specified source location.
|
||||
//
|
||||
func callers(q *Query) error {
|
||||
|
||||
2
vendor/golang.org/x/tools/cmd/guru/callstack.go
generated
vendored
2
vendor/golang.org/x/tools/cmd/guru/callstack.go
generated
vendored
@@ -16,7 +16,7 @@ import (
|
||||
"golang.org/x/tools/go/ssa/ssautil"
|
||||
)
|
||||
|
||||
// Callstack displays an arbitrary path from a root of the callgraph
|
||||
// The callstack function displays an arbitrary path from a root of the callgraph
|
||||
// to the function at the current position.
|
||||
//
|
||||
// The information may be misleading in a context-insensitive
|
||||
|
||||
10
vendor/golang.org/x/tools/cmd/guru/describe.go
generated
vendored
10
vendor/golang.org/x/tools/cmd/guru/describe.go
generated
vendored
@@ -8,7 +8,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
exact "go/constant"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"os"
|
||||
@@ -349,10 +349,10 @@ func describeValue(qpos *queryPos, path []ast.Node) (*describeValueResult, error
|
||||
|
||||
type describeValueResult struct {
|
||||
qpos *queryPos
|
||||
expr ast.Expr // query node
|
||||
typ types.Type // type of expression
|
||||
constVal exact.Value // value of expression, if constant
|
||||
obj types.Object // var/func/const object, if expr was Ident
|
||||
expr ast.Expr // query node
|
||||
typ types.Type // type of expression
|
||||
constVal constant.Value // value of expression, if constant
|
||||
obj types.Object // var/func/const object, if expr was Ident
|
||||
methods []*types.Selection
|
||||
fields []describeField
|
||||
}
|
||||
|
||||
18
vendor/golang.org/x/tools/cmd/guru/guru_test.go
generated
vendored
18
vendor/golang.org/x/tools/cmd/guru/guru_test.go
generated
vendored
@@ -35,6 +35,7 @@ import (
|
||||
"go/token"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -49,6 +50,18 @@ import (
|
||||
guru "golang.org/x/tools/cmd/guru"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// This test currently requires GOPATH mode.
|
||||
// Explicitly disabling module mode should suffix, but
|
||||
// we'll also turn off GOPROXY just for good measure.
|
||||
if err := os.Setenv("GO111MODULE", "off"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := os.Setenv("GOPROXY", "off"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
var updateFlag = flag.Bool("update", false, "Update the golden files.")
|
||||
|
||||
type query struct {
|
||||
@@ -268,11 +281,6 @@ func TestGuru(t *testing.T) {
|
||||
// tests once we drop support for go1.8.
|
||||
t.Skip()
|
||||
}
|
||||
if filename == "testdata/src/referrers/main.go" && !contains(build.Default.ReleaseTags, "go1.11") {
|
||||
// Disabling broken test on Go 1.9 and Go 1.10. https://golang.org/issue/24421
|
||||
// TODO(gri,adonovan): fix this test.
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
json := strings.Contains(filename, "-json/")
|
||||
queries := parseQueries(t, filename)
|
||||
|
||||
2
vendor/golang.org/x/tools/cmd/guru/implements.go
generated
vendored
2
vendor/golang.org/x/tools/cmd/guru/implements.go
generated
vendored
@@ -19,7 +19,7 @@ import (
|
||||
"golang.org/x/tools/refactor/importgraph"
|
||||
)
|
||||
|
||||
// Implements displays the "implements" relation as it pertains to the
|
||||
// The implements function displays the "implements" relation as it pertains to the
|
||||
// selected type.
|
||||
// If the selection is a method, 'implements' displays
|
||||
// the corresponding methods of the types that would have been reported
|
||||
|
||||
2
vendor/golang.org/x/tools/cmd/guru/referrers.go
generated
vendored
2
vendor/golang.org/x/tools/cmd/guru/referrers.go
generated
vendored
@@ -27,7 +27,7 @@ import (
|
||||
"golang.org/x/tools/refactor/importgraph"
|
||||
)
|
||||
|
||||
// Referrers reports all identifiers that resolve to the same object
|
||||
// The referrers function reports all identifiers that resolve to the same object
|
||||
// as the queried identifier, within any package in the workspace.
|
||||
func referrers(q *Query) error {
|
||||
fset := token.NewFileSet()
|
||||
|
||||
2
vendor/golang.org/x/tools/cmd/guru/testdata/src/referrers/main.golden
generated
vendored
2
vendor/golang.org/x/tools/cmd/guru/testdata/src/referrers/main.golden
generated
vendored
@@ -60,5 +60,5 @@ references to var notexported int
|
||||
|
||||
-------- @referrers ref-type-U --------
|
||||
references to type U int
|
||||
open nosuchfile.y: no such file or directory (+ 1 more refs in this file)
|
||||
open testdata/src/referrers/nosuchfile.y: no such file or directory (+ 1 more refs in this file)
|
||||
|
||||
|
||||
22
vendor/golang.org/x/tools/cmd/present/appengine.go
generated
vendored
22
vendor/golang.org/x/tools/cmd/present/appengine.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
// Copyright 2012 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 appengine
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"mime"
|
||||
|
||||
"golang.org/x/tools/present"
|
||||
)
|
||||
|
||||
func init() {
|
||||
initTemplates("./present/")
|
||||
present.PlayEnabled = true
|
||||
initPlayground("./present/", nil)
|
||||
|
||||
// App Engine has no /etc/mime.types
|
||||
mime.AddExtensionType(".svg", "image/svg+xml")
|
||||
}
|
||||
25
vendor/golang.org/x/tools/cmd/present/dir.go
generated
vendored
25
vendor/golang.org/x/tools/cmd/present/dir.go
generated
vendored
@@ -13,6 +13,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/present"
|
||||
)
|
||||
@@ -21,19 +22,18 @@ func init() {
|
||||
http.HandleFunc("/", dirHandler)
|
||||
}
|
||||
|
||||
// dirHandler serves a directory listing for the requested path, rooted at basePath.
|
||||
// dirHandler serves a directory listing for the requested path, rooted at *contentPath.
|
||||
func dirHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/favicon.ico" {
|
||||
http.Error(w, "not found", 404)
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
const base = "."
|
||||
name := filepath.Join(base, r.URL.Path)
|
||||
name := filepath.Join(*contentPath, r.URL.Path)
|
||||
if isDoc(name) {
|
||||
err := renderDoc(w, name)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
http.Error(w, err.Error(), 500)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -43,12 +43,12 @@ func dirHandler(w http.ResponseWriter, r *http.Request) {
|
||||
addr = r.RemoteAddr
|
||||
}
|
||||
log.Printf("request from %s: %s", addr, err)
|
||||
http.Error(w, err.Error(), 500)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
} else if isDir {
|
||||
return
|
||||
}
|
||||
http.FileServer(http.Dir(base)).ServeHTTP(w, r)
|
||||
http.FileServer(http.Dir(*contentPath)).ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func isDoc(path string) bool {
|
||||
@@ -138,7 +138,9 @@ func dirList(w io.Writer, name string) (isDir bool, err error) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
d := &dirListData{Path: name}
|
||||
strippedPath := strings.TrimPrefix(name, filepath.Clean(*contentPath))
|
||||
strippedPath = strings.TrimPrefix(strippedPath, "/")
|
||||
d := &dirListData{Path: strippedPath}
|
||||
for _, fi := range fis {
|
||||
// skip the golang.org directory
|
||||
if name == "." && fi.Name() == "golang.org" {
|
||||
@@ -146,15 +148,16 @@ func dirList(w io.Writer, name string) (isDir bool, err error) {
|
||||
}
|
||||
e := dirEntry{
|
||||
Name: fi.Name(),
|
||||
Path: filepath.ToSlash(filepath.Join(name, fi.Name())),
|
||||
Path: filepath.ToSlash(filepath.Join(strippedPath, fi.Name())),
|
||||
}
|
||||
if fi.IsDir() && showDir(e.Name) {
|
||||
d.Dirs = append(d.Dirs, e)
|
||||
continue
|
||||
}
|
||||
if isDoc(e.Name) {
|
||||
if p, err := parse(e.Path, present.TitlesOnly); err != nil {
|
||||
log.Println(err)
|
||||
fn := filepath.ToSlash(filepath.Join(name, fi.Name()))
|
||||
if p, err := parse(fn, present.TitlesOnly); err != nil {
|
||||
log.Printf("parse(%q, present.TitlesOnly): %v", fn, err)
|
||||
} else {
|
||||
e.Title = p.Title
|
||||
}
|
||||
|
||||
37
vendor/golang.org/x/tools/cmd/present/doc.go
generated
vendored
37
vendor/golang.org/x/tools/cmd/present/doc.go
generated
vendored
@@ -8,43 +8,38 @@ presents slide and article files from the current directory.
|
||||
|
||||
It may be run as a stand-alone command or an App Engine app.
|
||||
|
||||
Usage of present:
|
||||
-base="": base path for slide template and static resources
|
||||
-http="127.0.0.1:3999": HTTP service address (e.g., '127.0.0.1:3999')
|
||||
-nacl=false: use Native Client environment playground (prevents non-Go code execution)
|
||||
-notes=false: enable presenter notes (press 'N' from the browser to display them)
|
||||
-orighost="": host component of web origin URL (e.g., 'localhost')
|
||||
-play=true: enable playground (permit execution of arbitrary user code)
|
||||
|
||||
The setup of the Go version of NaCl is documented at:
|
||||
https://golang.org/wiki/NativeClient
|
||||
|
||||
To use with App Engine, copy the tools/cmd/present directory to the root of
|
||||
your application and create an app.yaml file similar to this:
|
||||
To use with App Engine, copy the files in the tools/cmd/present directory to the
|
||||
root of your application and create an app.yaml file similar to this:
|
||||
|
||||
application: [application]
|
||||
version: [version]
|
||||
runtime: go
|
||||
api_version: go1
|
||||
runtime: go111
|
||||
|
||||
handlers:
|
||||
- url: /favicon.ico
|
||||
static_files: present/static/favicon.ico
|
||||
upload: present/static/favicon.ico
|
||||
static_files: static/favicon.ico
|
||||
upload: static/favicon.ico
|
||||
- url: /static
|
||||
static_dir: present/static
|
||||
application_readable: true
|
||||
static_dir: static
|
||||
- url: /.*
|
||||
script: _go_app
|
||||
script: auto
|
||||
|
||||
# nobuild_files is a regexp that identifies which files to not build. It
|
||||
# is useful for embedding static assets like code snippets and preventing
|
||||
# them from producing build errors for your project.
|
||||
nobuild_files: [path regexp for talk materials]
|
||||
|
||||
When running on App Engine, content will be served from the ./content/
|
||||
subdirectory.
|
||||
|
||||
Present then can be tested in a local App Engine environment with
|
||||
|
||||
goapp serve
|
||||
GAE_ENV=standard go run .
|
||||
|
||||
And deployed using
|
||||
|
||||
gcloud app deploy
|
||||
|
||||
Input files are named foo.extension, where "extension" defines the format of
|
||||
the generated output. The supported formats are:
|
||||
@@ -54,4 +49,4 @@ the generated output. The supported formats are:
|
||||
The present file format is documented by the present package:
|
||||
http://godoc.org/golang.org/x/tools/present
|
||||
*/
|
||||
package main // import "golang.org/x/tools/cmd/present"
|
||||
package main
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !appengine
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -23,10 +21,12 @@ import (
|
||||
const basePkg = "golang.org/x/tools/cmd/present"
|
||||
|
||||
var (
|
||||
httpAddr = flag.String("http", "127.0.0.1:3999", "HTTP service address (e.g., '127.0.0.1:3999')")
|
||||
originHost = flag.String("orighost", "", "host component of web origin URL (e.g., 'localhost')")
|
||||
basePath = flag.String("base", "", "base path for slide template and static resources")
|
||||
nativeClient = flag.Bool("nacl", false, "use Native Client environment playground (prevents non-Go code execution)")
|
||||
httpAddr = flag.String("http", "127.0.0.1:3999", "HTTP service address (e.g., '127.0.0.1:3999')")
|
||||
originHost = flag.String("orighost", "", "host component of web origin URL (e.g., 'localhost')")
|
||||
basePath = flag.String("base", "", "base path for slide template and static resources")
|
||||
contentPath = flag.String("content", ".", "base path for presentation content")
|
||||
usePlayground = flag.Bool("use_playground", false, "run code snippets using play.golang.org; if false, run them locally and deliver results by WebSocket transport")
|
||||
nativeClient = flag.Bool("nacl", false, "use Native Client environment playground (prevents non-Go code execution) when using local WebSocket transport")
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -34,6 +34,22 @@ func main() {
|
||||
flag.BoolVar(&present.NotesEnabled, "notes", false, "enable presenter notes (press 'N' from the browser to display them)")
|
||||
flag.Parse()
|
||||
|
||||
if os.Getenv("GAE_ENV") == "standard" {
|
||||
log.Print("Configuring for App Engine Standard")
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = "8080"
|
||||
}
|
||||
*httpAddr = fmt.Sprintf("0.0.0.0:%s", port)
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't get pwd: %v\n", err)
|
||||
}
|
||||
*basePath = pwd
|
||||
*usePlayground = true
|
||||
*contentPath = "./content/"
|
||||
}
|
||||
|
||||
if *basePath == "" {
|
||||
p, err := build.Default.Import(basePkg, "", build.FindOnly)
|
||||
if err != nil {
|
||||
@@ -81,7 +97,7 @@ func main() {
|
||||
http.Handle("/static/", http.FileServer(http.Dir(*basePath)))
|
||||
|
||||
if !ln.Addr().(*net.TCPAddr).IP.IsLoopback() &&
|
||||
present.PlayEnabled && !*nativeClient {
|
||||
present.PlayEnabled && !*nativeClient && !*usePlayground {
|
||||
log.Print(localhostWarning)
|
||||
}
|
||||
|
||||
@@ -121,11 +137,12 @@ You may use the -base flag to specify an alternate location.
|
||||
const localhostWarning = `
|
||||
WARNING! WARNING! WARNING!
|
||||
|
||||
The present server appears to be listening on an address that is not localhost.
|
||||
Anyone with access to this address and port will have access to this machine as
|
||||
the user running present.
|
||||
The present server appears to be listening on an address that is not localhost
|
||||
and is configured to run code snippets locally. Anyone with access to this address
|
||||
and port will have access to this machine as the user running present.
|
||||
|
||||
To avoid this message, listen on localhost or run with -play=false.
|
||||
To avoid this message, listen on localhost, run with -play=false, or run with
|
||||
-play_socket=false.
|
||||
|
||||
If you don't understand this message, hit Control-C to terminate this process.
|
||||
|
||||
46
vendor/golang.org/x/tools/cmd/present/play.go
generated
vendored
46
vendor/golang.org/x/tools/cmd/present/play.go
generated
vendored
@@ -9,10 +9,21 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"golang.org/x/tools/godoc/static"
|
||||
"golang.org/x/tools/playground/socket"
|
||||
"golang.org/x/tools/present"
|
||||
|
||||
// This will register handlers at /compile and /share that will proxy to the
|
||||
// respective endpoints at play.golang.org. This allows the frontend to call
|
||||
// these endpoints without needing cross-origin request sharing (CORS).
|
||||
// Note that this is imported regardless of whether the endpoints are used or
|
||||
// not (in the case of a local socket connection, they are not called).
|
||||
_ "golang.org/x/tools/playground"
|
||||
)
|
||||
|
||||
var scripts = []string{"jquery.js", "jquery-ui.js", "playground.js", "play.js"}
|
||||
@@ -41,3 +52,38 @@ func playScript(root, transport string) {
|
||||
http.ServeContent(w, r, "", modTime, bytes.NewReader(b))
|
||||
})
|
||||
}
|
||||
|
||||
func initPlayground(basepath string, origin *url.URL) {
|
||||
if !present.PlayEnabled {
|
||||
return
|
||||
}
|
||||
if *usePlayground {
|
||||
playScript(basepath, "HTTPTransport")
|
||||
return
|
||||
}
|
||||
|
||||
if *nativeClient {
|
||||
// When specifying nativeClient, non-Go code cannot be executed
|
||||
// because the NaCl setup doesn't support doing so.
|
||||
socket.RunScripts = false
|
||||
socket.Environ = func() []string {
|
||||
if runtime.GOARCH == "amd64" {
|
||||
return environ("GOOS=nacl", "GOARCH=amd64p32")
|
||||
}
|
||||
return environ("GOOS=nacl")
|
||||
}
|
||||
}
|
||||
playScript(basepath, "SocketTransport")
|
||||
http.Handle("/socket", socket.NewHandler(origin))
|
||||
}
|
||||
|
||||
func playable(c present.Code) bool {
|
||||
play := present.PlayEnabled && c.Play
|
||||
|
||||
// Restrict playable files to only Go source files when using play.golang.org,
|
||||
// since there is no method to execute shell scripts there.
|
||||
if *usePlayground {
|
||||
return play && c.Ext == ".go"
|
||||
}
|
||||
return play
|
||||
}
|
||||
|
||||
23
vendor/golang.org/x/tools/cmd/present/play_http.go
generated
vendored
23
vendor/golang.org/x/tools/cmd/present/play_http.go
generated
vendored
@@ -1,23 +0,0 @@
|
||||
// Copyright 2015 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 appengine appenginevm
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/tools/present"
|
||||
|
||||
_ "golang.org/x/tools/playground"
|
||||
)
|
||||
|
||||
func initPlayground(basepath string, origin *url.URL) {
|
||||
playScript(basepath, "HTTPTransport")
|
||||
}
|
||||
|
||||
func playable(c present.Code) bool {
|
||||
return present.PlayEnabled && c.Play && c.Ext == ".go"
|
||||
}
|
||||
36
vendor/golang.org/x/tools/cmd/present/play_socket.go
generated
vendored
36
vendor/golang.org/x/tools/cmd/present/play_socket.go
generated
vendored
@@ -1,36 +0,0 @@
|
||||
// Copyright 2015 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 !appengine,!appenginevm
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/tools/playground/socket"
|
||||
"golang.org/x/tools/present"
|
||||
)
|
||||
|
||||
func initPlayground(basepath string, origin *url.URL) {
|
||||
if present.PlayEnabled {
|
||||
if *nativeClient {
|
||||
socket.RunScripts = false
|
||||
socket.Environ = func() []string {
|
||||
if runtime.GOARCH == "amd64" {
|
||||
return environ("GOOS=nacl", "GOARCH=amd64p32")
|
||||
}
|
||||
return environ("GOOS=nacl")
|
||||
}
|
||||
}
|
||||
playScript(basepath, "SocketTransport")
|
||||
http.Handle("/socket", socket.NewHandler(origin))
|
||||
}
|
||||
}
|
||||
|
||||
func playable(c present.Code) bool {
|
||||
return present.PlayEnabled && c.Play
|
||||
}
|
||||
130
vendor/golang.org/x/tools/cmd/ssadump/main.go
generated
vendored
130
vendor/golang.org/x/tools/cmd/ssadump/main.go
generated
vendored
@@ -15,7 +15,7 @@ import (
|
||||
"runtime/pprof"
|
||||
|
||||
"golang.org/x/tools/go/buildutil"
|
||||
"golang.org/x/tools/go/loader"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"golang.org/x/tools/go/ssa"
|
||||
"golang.org/x/tools/go/ssa/interp"
|
||||
"golang.org/x/tools/go/ssa/ssautil"
|
||||
@@ -25,9 +25,9 @@ import (
|
||||
var (
|
||||
mode = ssa.BuilderMode(0)
|
||||
|
||||
testFlag = flag.Bool("test", false, "Loads test code (*_test.go) for imported packages.")
|
||||
testFlag = flag.Bool("test", false, "include implicit test packages and executables")
|
||||
|
||||
runFlag = flag.Bool("run", false, "Invokes the SSA interpreter on the program.")
|
||||
runFlag = flag.Bool("run", false, "interpret the SSA program")
|
||||
|
||||
interpFlag = flag.String("interp", "", `Options controlling the SSA test interpreter.
|
||||
The value is a sequence of zero or more more of these letters:
|
||||
@@ -36,23 +36,25 @@ T [T]race execution of the program. Best for single-threaded programs!
|
||||
`)
|
||||
|
||||
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
|
||||
|
||||
args stringListValue
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Var(&mode, "build", ssa.BuilderModeDoc)
|
||||
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
|
||||
flag.Var(&args, "arg", "add argument to interpreted program")
|
||||
}
|
||||
|
||||
const usage = `SSA builder and interpreter.
|
||||
Usage: ssadump [<flag> ...] <args> ...
|
||||
Usage: ssadump [-build=[DBCSNFL]] [-test] [-run] [-interp=[TR]] [-arg=...] package...
|
||||
Use -help flag to display options.
|
||||
|
||||
Examples:
|
||||
% ssadump -build=F hello.go # dump SSA form of a single package
|
||||
% ssadump -build=F -test fmt # dump SSA form of a package and its tests
|
||||
% ssadump -run -interp=T hello.go # interpret a program, with tracing
|
||||
` + loader.FromArgsUsage +
|
||||
`
|
||||
|
||||
The -run flag causes ssadump to run the first package named main.
|
||||
|
||||
Interpretation of the standard "testing" package is no longer supported.
|
||||
@@ -67,17 +69,24 @@ func main() {
|
||||
|
||||
func doMain() error {
|
||||
flag.Parse()
|
||||
args := flag.Args()
|
||||
if len(flag.Args()) == 0 {
|
||||
fmt.Fprint(os.Stderr, usage)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
conf := loader.Config{Build: &build.Default}
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.LoadSyntax,
|
||||
Tests: *testFlag,
|
||||
}
|
||||
|
||||
// Choose types.Sizes from conf.Build.
|
||||
// TODO(adonovan): remove this when go/packages provides a better way.
|
||||
var wordSize int64 = 8
|
||||
switch conf.Build.GOARCH {
|
||||
switch build.Default.GOARCH {
|
||||
case "386", "arm":
|
||||
wordSize = 4
|
||||
}
|
||||
conf.TypeChecker.Sizes = &types.StdSizes{
|
||||
sizes := &types.StdSizes{
|
||||
MaxAlign: 8,
|
||||
WordSize: wordSize,
|
||||
}
|
||||
@@ -94,11 +103,6 @@ func doMain() error {
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
fmt.Fprint(os.Stderr, usage)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Profiling support.
|
||||
if *cpuprofile != "" {
|
||||
f, err := os.Create(*cpuprofile)
|
||||
@@ -110,58 +114,49 @@ func doMain() error {
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
// Use the initial packages from the command line.
|
||||
args, err := conf.FromArgs(args, *testFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// The interpreter needs the runtime package.
|
||||
// Load, parse and type-check the initial packages,
|
||||
// and, if -run, their dependencies.
|
||||
if *runFlag {
|
||||
conf.Import("runtime")
|
||||
cfg.Mode = packages.LoadAllSyntax
|
||||
}
|
||||
|
||||
// Load, parse and type-check the whole program.
|
||||
lprog, err := conf.Load()
|
||||
initial, err := packages.Load(cfg, flag.Args()...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(initial) == 0 {
|
||||
return fmt.Errorf("no packages")
|
||||
}
|
||||
if packages.PrintErrors(initial) > 0 {
|
||||
return fmt.Errorf("packages contain errors")
|
||||
}
|
||||
|
||||
// Create and build SSA-form program representation.
|
||||
prog := ssautil.CreateProgram(lprog, mode)
|
||||
// Create SSA-form program representation.
|
||||
prog, pkgs := ssautil.AllPackages(initial, mode)
|
||||
|
||||
// Build and display only the initial packages
|
||||
// (and synthetic wrappers), unless -run is specified.
|
||||
var initpkgs []*ssa.Package
|
||||
for _, info := range lprog.InitialPackages() {
|
||||
ssapkg := prog.Package(info.Pkg)
|
||||
ssapkg.Build()
|
||||
if info.Pkg.Path() != "runtime" {
|
||||
initpkgs = append(initpkgs, ssapkg)
|
||||
for i, p := range pkgs {
|
||||
if p == nil {
|
||||
return fmt.Errorf("cannot build SSA for package %s", initial[i])
|
||||
}
|
||||
}
|
||||
|
||||
// Run the interpreter.
|
||||
if *runFlag {
|
||||
if !*runFlag {
|
||||
// Build and display only the initial packages
|
||||
// (and synthetic wrappers).
|
||||
for _, p := range pkgs {
|
||||
p.Build()
|
||||
}
|
||||
|
||||
} else {
|
||||
// Run the interpreter.
|
||||
// Build SSA for all packages.
|
||||
prog.Build()
|
||||
|
||||
var mains []*ssa.Package
|
||||
if *testFlag {
|
||||
// If -test, run the tests.
|
||||
for _, pkg := range initpkgs {
|
||||
if main := prog.CreateTestMainPackage(pkg); main != nil {
|
||||
mains = append(mains, main)
|
||||
}
|
||||
}
|
||||
if mains == nil {
|
||||
return fmt.Errorf("no tests")
|
||||
}
|
||||
} else {
|
||||
// Otherwise, run the main packages.
|
||||
mains = ssautil.MainPackages(initpkgs)
|
||||
if len(mains) == 0 {
|
||||
return fmt.Errorf("no main package")
|
||||
}
|
||||
// The interpreter needs the runtime package.
|
||||
// It is a limitation of go/packages that
|
||||
// we cannot add "runtime" to its initial set,
|
||||
// we can only check that it is present.
|
||||
if prog.ImportedPackage("runtime") == nil {
|
||||
return fmt.Errorf("-run: program does not depend on runtime")
|
||||
}
|
||||
|
||||
if runtime.GOARCH != build.Default.GOARCH {
|
||||
@@ -169,12 +164,27 @@ func doMain() error {
|
||||
build.Default.GOARCH, runtime.GOARCH)
|
||||
}
|
||||
|
||||
for _, main := range mains {
|
||||
if len(mains) > 1 {
|
||||
fmt.Fprintf(os.Stderr, "Running: %s\n", main.Pkg.Path())
|
||||
}
|
||||
interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Pkg.Path(), args)
|
||||
// Run first main package.
|
||||
for _, main := range ssautil.MainPackages(pkgs) {
|
||||
fmt.Fprintf(os.Stderr, "Running: %s\n", main.Pkg.Path())
|
||||
os.Exit(interp.Interpret(main, interpMode, sizes, main.Pkg.Path(), args))
|
||||
}
|
||||
return fmt.Errorf("no main package")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// stringListValue is a flag.Value that accumulates strings.
|
||||
// e.g. --flag=one --flag=two would produce []string{"one", "two"}.
|
||||
type stringListValue []string
|
||||
|
||||
func newStringListValue(val []string, p *[]string) *stringListValue {
|
||||
*p = val
|
||||
return (*stringListValue)(p)
|
||||
}
|
||||
|
||||
func (ss *stringListValue) Get() interface{} { return []string(*ss) }
|
||||
|
||||
func (ss *stringListValue) String() string { return fmt.Sprintf("%q", *ss) }
|
||||
|
||||
func (ss *stringListValue) Set(s string) error { *ss = append(*ss, s); return nil }
|
||||
|
||||
32
vendor/golang.org/x/tools/cmd/stringer/stringer.go
generated
vendored
32
vendor/golang.org/x/tools/cmd/stringer/stringer.go
generated
vendored
@@ -64,7 +64,7 @@ import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
exact "go/constant"
|
||||
"go/constant"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
@@ -87,7 +87,7 @@ var (
|
||||
|
||||
// Usage is a replacement usage function for the flags package.
|
||||
func Usage() {
|
||||
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
|
||||
fmt.Fprintf(os.Stderr, "Usage of stringer:\n")
|
||||
fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T [directory]\n")
|
||||
fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T files... # Must be a single package\n")
|
||||
fmt.Fprintf(os.Stderr, "For more information, see:\n")
|
||||
@@ -390,7 +390,7 @@ type Value struct {
|
||||
// by Value.String.
|
||||
value uint64 // Will be converted to int64 when needed.
|
||||
signed bool // Whether the constant is a signed type.
|
||||
str string // The string representation given by the "go/exact" package.
|
||||
str string // The string representation given by the "go/constant" package.
|
||||
}
|
||||
|
||||
func (v *Value) String() string {
|
||||
@@ -428,10 +428,24 @@ func (f *File) genDecl(node ast.Node) bool {
|
||||
for _, spec := range decl.Specs {
|
||||
vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST.
|
||||
if vspec.Type == nil && len(vspec.Values) > 0 {
|
||||
// "X = 1". With no type but a value, the constant is untyped.
|
||||
// Skip this vspec and reset the remembered type.
|
||||
// "X = 1". With no type but a value. If the constant is untyped,
|
||||
// skip this vspec and reset the remembered type.
|
||||
typ = ""
|
||||
continue
|
||||
|
||||
// If this is a simple type conversion, remember the type.
|
||||
// We don't mind if this is actually a call; a qualified call won't
|
||||
// be matched (that will be SelectorExpr, not Ident), and only unusual
|
||||
// situations will result in a function call that appears to be
|
||||
// a type conversion.
|
||||
ce, ok := vspec.Values[0].(*ast.CallExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
id, ok := ce.Fun.(*ast.Ident)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
typ = id.Name
|
||||
}
|
||||
if vspec.Type != nil {
|
||||
// "X T". We have a type. Remember it.
|
||||
@@ -464,11 +478,11 @@ func (f *File) genDecl(node ast.Node) bool {
|
||||
log.Fatalf("can't handle non-integer constant type %s", typ)
|
||||
}
|
||||
value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST.
|
||||
if value.Kind() != exact.Int {
|
||||
if value.Kind() != constant.Int {
|
||||
log.Fatalf("can't happen: constant is not an integer %s", name)
|
||||
}
|
||||
i64, isInt := exact.Int64Val(value)
|
||||
u64, isUint := exact.Uint64Val(value)
|
||||
i64, isInt := constant.Int64Val(value)
|
||||
u64, isUint := constant.Uint64Val(value)
|
||||
if !isInt && !isUint {
|
||||
log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String())
|
||||
}
|
||||
|
||||
41
vendor/golang.org/x/tools/cmd/stringer/testdata/conv.go
generated
vendored
Normal file
41
vendor/golang.org/x/tools/cmd/stringer/testdata/conv.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// Check that constants defined as a conversion are accepted.
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Other int // Imagine this is in another package.
|
||||
|
||||
const (
|
||||
alpha Other = iota
|
||||
beta
|
||||
gamma
|
||||
delta
|
||||
)
|
||||
|
||||
type Conv int
|
||||
|
||||
const (
|
||||
Alpha = Conv(alpha)
|
||||
Beta = Conv(beta)
|
||||
Gamma = Conv(gamma)
|
||||
Delta = Conv(delta)
|
||||
)
|
||||
|
||||
func main() {
|
||||
ck(Alpha, "Alpha")
|
||||
ck(Beta, "Beta")
|
||||
ck(Gamma, "Gamma")
|
||||
ck(Delta, "Delta")
|
||||
ck(42, "Conv(42)")
|
||||
}
|
||||
|
||||
func ck(c Conv, str string) {
|
||||
if fmt.Sprint(c) != str {
|
||||
panic("conv.go: " + str)
|
||||
}
|
||||
}
|
||||
3
vendor/golang.org/x/tools/cmd/tip/Dockerfile
generated
vendored
3
vendor/golang.org/x/tools/cmd/tip/Dockerfile
generated
vendored
@@ -135,7 +135,8 @@ RUN go install cloud.google.com/go/compute/metadata \
|
||||
|
||||
# golang sets GOPATH=/go
|
||||
ADD . /go/src/tip
|
||||
RUN go install --tags=autocert tip
|
||||
WORKDIR /go/src/tip
|
||||
RUN go install --tags=autocert
|
||||
ENTRYPOINT ["/go/bin/tip"]
|
||||
|
||||
# We listen on 8080 (for historical reasons). The service.yaml maps public port 80 to 8080.
|
||||
|
||||
33
vendor/golang.org/x/tools/cmd/tip/Makefile
generated
vendored
33
vendor/golang.org/x/tools/cmd/tip/Makefile
generated
vendored
@@ -2,7 +2,11 @@
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
VERSION=v2
|
||||
VERSION ?= $(shell git rev-parse --short HEAD)
|
||||
MUTABLE_VERSION ?= latest
|
||||
|
||||
IMAGE_STAGING := gcr.io/go-dashboard-dev/tip
|
||||
IMAGE_PROD := gcr.io/symbolic-datum-552/tip
|
||||
|
||||
.PHONY: usage
|
||||
|
||||
@@ -14,12 +18,23 @@ update-deps:
|
||||
go install golang.org/x/build/cmd/gitlock
|
||||
gitlock --update=Dockerfile --ignore=NONE --tags=autocert golang.org/x/tools/cmd/tip
|
||||
|
||||
docker-prod: Dockerfile
|
||||
docker build -f Dockerfile --tag=gcr.io/symbolic-datum-552/tip:$(VERSION) .
|
||||
docker-dev: Dockerfile
|
||||
docker build -f Dockerfile --tag=gcr.io/go-dashboard-dev/tip:$(VERSION) .
|
||||
docker-image: Dockerfile *.go
|
||||
docker build --force-rm -f Dockerfile --tag=$(IMAGE_PROD):$(VERSION) .
|
||||
docker tag $(IMAGE_PROD):$(VERSION) $(IMAGE_PROD):$(MUTABLE_VERSION)
|
||||
docker tag $(IMAGE_PROD):$(VERSION) $(IMAGE_STAGING):$(VERSION)
|
||||
docker tag $(IMAGE_PROD):$(VERSION) $(IMAGE_STAGING):$(MUTABLE_VERSION)
|
||||
|
||||
push-prod: docker-image
|
||||
docker push $(IMAGE_PROD):$(MUTABLE_VERSION)
|
||||
docker push $(IMAGE_PROD):$(VERSION)
|
||||
push-staging: docker-image
|
||||
docker push $(IMAGE_STAGING):$(MUTABLE_VERSION)
|
||||
docker push $(IMAGE_STAGING):$(VERSION)
|
||||
|
||||
deploy-prod: push-prod
|
||||
go install golang.org/x/build/cmd/xb
|
||||
xb --prod kubectl set image deployment/tip-deployment tip=$(IMAGE_PROD):$(VERSION)
|
||||
deploy-staging: push-staging
|
||||
go install golang.org/x/build/cmd/xb
|
||||
xb --staging kubectl set image deployment/tip-deployment tip=$(IMAGE_STAGING):$(VERSION)
|
||||
|
||||
push-prod: docker-prod
|
||||
gcloud docker -- push gcr.io/symbolic-datum-552/tip:$(VERSION)
|
||||
push-dev: docker-dev
|
||||
gcloud docker -- push gcr.io/go-dashboard-dev/tip:$(VERSION)
|
||||
|
||||
3
vendor/golang.org/x/tools/cmd/tip/cert.go
generated
vendored
3
vendor/golang.org/x/tools/cmd/tip/cert.go
generated
vendored
@@ -17,6 +17,7 @@ import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"cloud.google.com/go/storage"
|
||||
"golang.org/x/build/autocertcache"
|
||||
@@ -42,7 +43,7 @@ func certInitAutocert() {
|
||||
}
|
||||
autocertManager = &autocert.Manager{
|
||||
Prompt: autocert.AcceptTOS,
|
||||
HostPolicy: autocert.HostWhitelist(*autoCertDomain),
|
||||
HostPolicy: autocert.HostWhitelist(strings.Split(*autoCertDomain, ",")...),
|
||||
Cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/golang.org/x/tools/cmd/tip/godoc.go
generated
vendored
2
vendor/golang.org/x/tools/cmd/tip/godoc.go
generated
vendored
@@ -48,7 +48,7 @@ func (b godocBuilder) Init(dir, hostport string, heads map[string]string) (*exec
|
||||
}
|
||||
|
||||
godocBin := filepath.Join(goPath, "bin/godoc")
|
||||
godoc := exec.Command(godocBin, "-http="+hostport, "-index", "-index_interval=-1s")
|
||||
godoc := exec.Command(godocBin, "-http="+hostport, "-index", "-index_interval=-1s", "-play")
|
||||
godoc.Env = []string{"GOROOT=" + goDir}
|
||||
// TODO(adg): log this somewhere useful
|
||||
godoc.Stdout = os.Stdout
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
apiVersion: v1
|
||||
kind: ReplicationController
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: tipgodoc
|
||||
name: tipgodoc-deployment
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
app: tipgodoc
|
||||
template:
|
||||
metadata:
|
||||
name: tipgodoc
|
||||
@@ -16,10 +14,10 @@ spec:
|
||||
- name: cache-volume
|
||||
emptyDir: {}
|
||||
containers:
|
||||
- name: gitmirror
|
||||
image: gcr.io/symbolic-datum-552/tip:v2
|
||||
- name: tipgodoc
|
||||
image: gcr.io/symbolic-datum-552/tip:latest
|
||||
imagePullPolicy: Always
|
||||
command: ["/go/bin/tip", "--autocert=tip.golang.org", "--autocert-bucket=golang-tip-autocert"]
|
||||
command: ["/go/bin/tip", "--autocert=tip.golang.org,beta.golang.org", "--autocert-bucket=golang-tip-autocert"]
|
||||
env:
|
||||
- name: TMPDIR
|
||||
value: /build
|
||||
14
vendor/golang.org/x/tools/cmd/tip/tip.go
generated
vendored
14
vendor/golang.org/x/tools/cmd/tip/tip.go
generated
vendored
@@ -34,7 +34,7 @@ const (
|
||||
var startTime = time.Now()
|
||||
|
||||
var (
|
||||
autoCertDomain = flag.String("autocert", "", "if non-empty, listen on port 443 and serve a LetsEncrypt cert for this hostname")
|
||||
autoCertDomain = flag.String("autocert", "", "if non-empty, listen on port 443 and serve a LetsEncrypt cert for this hostname or hostnames (comma-separated)")
|
||||
autoCertCacheBucket = flag.String("autocert-bucket", "", "if non-empty, the Google Cloud Storage bucket in which to store the LetsEncrypt cache")
|
||||
)
|
||||
|
||||
@@ -120,6 +120,18 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
p.serveStatus(w, r)
|
||||
return
|
||||
}
|
||||
// Redirect the old beta.golang.org URL to tip.golang.org,
|
||||
// just in case there are old links out there to
|
||||
// beta.golang.org. (We used to run a "temporary" beta.golang.org
|
||||
// GCE VM running godoc where "temporary" lasted two years.
|
||||
// So it lasted so long, there are probably links to it out there.)
|
||||
if r.Host == "beta.golang.org" {
|
||||
u := *r.URL
|
||||
u.Scheme = "https"
|
||||
u.Host = "tip.golang.org"
|
||||
http.Redirect(w, r, u.String(), http.StatusFound)
|
||||
return
|
||||
}
|
||||
p.mu.Lock()
|
||||
proxy := p.proxy
|
||||
err := p.err
|
||||
|
||||
192
vendor/golang.org/x/tools/go/analysis/analysis.go
generated
vendored
Normal file
192
vendor/golang.org/x/tools/go/analysis/analysis.go
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
package analysis
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// An Analyzer describes an analysis function and its options.
|
||||
type Analyzer struct {
|
||||
// The Name of the analyzer must be a valid Go identifier
|
||||
// as it may appear in command-line flags, URLs, and so on.
|
||||
Name string
|
||||
|
||||
// Doc is the documentation for the analyzer.
|
||||
// The part before the first "\n\n" is the title
|
||||
// (no capital or period, max ~60 letters).
|
||||
Doc string
|
||||
|
||||
// Flags defines any flags accepted by the analyzer.
|
||||
// The manner in which these flags are exposed to the user
|
||||
// depends on the driver which runs the analyzer.
|
||||
Flags flag.FlagSet
|
||||
|
||||
// Run applies the analyzer to a package.
|
||||
// It returns an error if the analyzer failed.
|
||||
//
|
||||
// On success, the Run function may return a result
|
||||
// computed by the Analyzer; its type must match ResultType.
|
||||
// The driver makes this result available as an input to
|
||||
// another Analyzer that depends directly on this one (see
|
||||
// Requires) when it analyzes the same package.
|
||||
//
|
||||
// To pass analysis results between packages (and thus
|
||||
// potentially between address spaces), use Facts, which are
|
||||
// serializable.
|
||||
Run func(*Pass) (interface{}, error)
|
||||
|
||||
// RunDespiteErrors allows the driver to invoke
|
||||
// the Run method of this analyzer even on a
|
||||
// package that contains parse or type errors.
|
||||
RunDespiteErrors bool
|
||||
|
||||
// Requires is a set of analyzers that must run successfully
|
||||
// before this one on a given package. This analyzer may inspect
|
||||
// the outputs produced by each analyzer in Requires.
|
||||
// The graph over analyzers implied by Requires edges must be acyclic.
|
||||
//
|
||||
// Requires establishes a "horizontal" dependency between
|
||||
// analysis passes (different analyzers, same package).
|
||||
Requires []*Analyzer
|
||||
|
||||
// ResultType is the type of the optional result of the Run function.
|
||||
ResultType reflect.Type
|
||||
|
||||
// FactTypes indicates that this analyzer imports and exports
|
||||
// Facts of the specified concrete types.
|
||||
// An analyzer that uses facts may assume that its import
|
||||
// dependencies have been similarly analyzed before it runs.
|
||||
// Facts must be pointers.
|
||||
//
|
||||
// FactTypes establishes a "vertical" dependency between
|
||||
// analysis passes (same analyzer, different packages).
|
||||
FactTypes []Fact
|
||||
}
|
||||
|
||||
func (a *Analyzer) String() string { return a.Name }
|
||||
|
||||
// A Pass provides information to the Run function that
|
||||
// applies a specific analyzer to a single Go package.
|
||||
//
|
||||
// It forms the interface between the analysis logic and the driver
|
||||
// program, and has both input and an output components.
|
||||
//
|
||||
// As in a compiler, one pass may depend on the result computed by another.
|
||||
//
|
||||
// The Run function should not call any of the Pass functions concurrently.
|
||||
type Pass struct {
|
||||
Analyzer *Analyzer // the identity of the current analyzer
|
||||
|
||||
// syntax and type information
|
||||
Fset *token.FileSet // file position information
|
||||
Files []*ast.File // the abstract syntax tree of each file
|
||||
OtherFiles []string // names of non-Go files of this package
|
||||
Pkg *types.Package // type information about the package
|
||||
TypesInfo *types.Info // type information about the syntax trees
|
||||
|
||||
// Report reports a Diagnostic, a finding about a specific location
|
||||
// in the analyzed source code such as a potential mistake.
|
||||
// It may be called by the Run function.
|
||||
Report func(Diagnostic)
|
||||
|
||||
// ResultOf provides the inputs to this analysis pass, which are
|
||||
// the corresponding results of its prerequisite analyzers.
|
||||
// The map keys are the elements of Analysis.Required,
|
||||
// and the type of each corresponding value is the required
|
||||
// analysis's ResultType.
|
||||
ResultOf map[*Analyzer]interface{}
|
||||
|
||||
// -- facts --
|
||||
|
||||
// ImportObjectFact retrieves a fact associated with obj.
|
||||
// Given a value ptr of type *T, where *T satisfies Fact,
|
||||
// ImportObjectFact copies the value to *ptr.
|
||||
//
|
||||
// ImportObjectFact panics if called after the pass is complete.
|
||||
// ImportObjectFact is not concurrency-safe.
|
||||
ImportObjectFact func(obj types.Object, fact Fact) bool
|
||||
|
||||
// ImportPackageFact retrieves a fact associated with package pkg,
|
||||
// which must be this package or one of its dependencies.
|
||||
// See comments for ImportObjectFact.
|
||||
ImportPackageFact func(pkg *types.Package, fact Fact) bool
|
||||
|
||||
// ExportObjectFact associates a fact of type *T with the obj,
|
||||
// replacing any previous fact of that type.
|
||||
//
|
||||
// ExportObjectFact panics if it is called after the pass is
|
||||
// complete, or if obj does not belong to the package being analyzed.
|
||||
// ExportObjectFact is not concurrency-safe.
|
||||
ExportObjectFact func(obj types.Object, fact Fact)
|
||||
|
||||
// ExportPackageFact associates a fact with the current package.
|
||||
// See comments for ExportObjectFact.
|
||||
ExportPackageFact func(fact Fact)
|
||||
|
||||
/* Further fields may be added in future. */
|
||||
// For example, suggested or applied refactorings.
|
||||
}
|
||||
|
||||
// Reportf is a helper function that reports a Diagnostic using the
|
||||
// specified position and formatted error message.
|
||||
func (pass *Pass) Reportf(pos token.Pos, format string, args ...interface{}) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
pass.Report(Diagnostic{Pos: pos, Message: msg})
|
||||
}
|
||||
|
||||
func (pass *Pass) String() string {
|
||||
return fmt.Sprintf("%s@%s", pass.Analyzer.Name, pass.Pkg.Path())
|
||||
}
|
||||
|
||||
// A Fact is an intermediate fact produced during analysis.
|
||||
//
|
||||
// Each fact is associated with a named declaration (a types.Object) or
|
||||
// with a package as a whole. A single object or package may have
|
||||
// multiple associated facts, but only one of any particular fact type.
|
||||
//
|
||||
// A Fact represents a predicate such as "never returns", but does not
|
||||
// represent the subject of the predicate such as "function F" or "package P".
|
||||
//
|
||||
// Facts may be produced in one analysis pass and consumed by another
|
||||
// analysis pass even if these are in different address spaces.
|
||||
// If package P imports Q, all facts about Q produced during
|
||||
// analysis of that package will be available during later analysis of P.
|
||||
// Facts are analogous to type export data in a build system:
|
||||
// just as export data enables separate compilation of several passes,
|
||||
// facts enable "separate analysis".
|
||||
//
|
||||
// Each pass (a, p) starts with the set of facts produced by the
|
||||
// same analyzer a applied to the packages directly imported by p.
|
||||
// The analysis may add facts to the set, and they may be exported in turn.
|
||||
// An analysis's Run function may retrieve facts by calling
|
||||
// Pass.Import{Object,Package}Fact and update them using
|
||||
// Pass.Export{Object,Package}Fact.
|
||||
//
|
||||
// A fact is logically private to its Analysis. To pass values
|
||||
// between different analyzers, use the results mechanism;
|
||||
// see Analyzer.Requires, Analyzer.ResultType, and Pass.ResultOf.
|
||||
//
|
||||
// A Fact type must be a pointer.
|
||||
// Facts are encoded and decoded using encoding/gob.
|
||||
// A Fact may implement the GobEncoder/GobDecoder interfaces
|
||||
// to customize its encoding. Fact encoding should not fail.
|
||||
//
|
||||
// A Fact should not be modified once exported.
|
||||
type Fact interface {
|
||||
AFact() // dummy method to avoid type errors
|
||||
}
|
||||
|
||||
// A Diagnostic is a message associated with a source location.
|
||||
//
|
||||
// An Analyzer may return a variety of diagnostics; the optional Category,
|
||||
// which should be a constant, may be used to classify them.
|
||||
// It is primarily intended to make it easy to look up documentation.
|
||||
type Diagnostic struct {
|
||||
Pos token.Pos
|
||||
Category string // optional
|
||||
Message string
|
||||
}
|
||||
387
vendor/golang.org/x/tools/go/analysis/analysistest/analysistest.go
generated
vendored
Normal file
387
vendor/golang.org/x/tools/go/analysis/analysistest/analysistest.go
generated
vendored
Normal file
@@ -0,0 +1,387 @@
|
||||
// Package analysistest provides utilities for testing analyzers.
|
||||
package analysistest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/scanner"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/internal/checker"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
// WriteFiles is a helper function that creates a temporary directory
|
||||
// and populates it with a GOPATH-style project using filemap (which
|
||||
// maps file names to contents). On success it returns the name of the
|
||||
// directory and a cleanup function to delete it.
|
||||
func WriteFiles(filemap map[string]string) (dir string, cleanup func(), err error) {
|
||||
gopath, err := ioutil.TempDir("", "analysistest")
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
cleanup = func() { os.RemoveAll(gopath) }
|
||||
|
||||
for name, content := range filemap {
|
||||
filename := filepath.Join(gopath, "src", name)
|
||||
os.MkdirAll(filepath.Dir(filename), 0777) // ignore error
|
||||
if err := ioutil.WriteFile(filename, []byte(content), 0666); err != nil {
|
||||
cleanup()
|
||||
return "", nil, err
|
||||
}
|
||||
}
|
||||
return gopath, cleanup, nil
|
||||
}
|
||||
|
||||
// TestData returns the effective filename of
|
||||
// the program's "testdata" directory.
|
||||
// This function may be overridden by projects using
|
||||
// an alternative build system (such as Blaze) that
|
||||
// does not run a test in its package directory.
|
||||
var TestData = func() string {
|
||||
testdata, err := filepath.Abs("testdata")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return testdata
|
||||
}
|
||||
|
||||
// Testing is an abstraction of a *testing.T.
|
||||
type Testing interface {
|
||||
Errorf(format string, args ...interface{})
|
||||
}
|
||||
|
||||
// Run applies an analysis to the packages denoted by the "go list" patterns.
|
||||
//
|
||||
// It loads the packages from the specified GOPATH-style project
|
||||
// directory using golang.org/x/tools/go/packages, runs the analysis on
|
||||
// them, and checks that each analysis emits the expected diagnostics
|
||||
// and facts specified by the contents of '// want ...' comments in the
|
||||
// package's source files.
|
||||
//
|
||||
// An expectation of a Diagnostic is specified by a string literal
|
||||
// containing a regular expression that must match the diagnostic
|
||||
// message. For example:
|
||||
//
|
||||
// fmt.Printf("%s", 1) // want `cannot provide int 1 to %s`
|
||||
//
|
||||
// An expectation of a Fact associated with an object is specified by
|
||||
// 'name:"pattern"', where name is the name of the object, which must be
|
||||
// declared on the same line as the comment, and pattern is a regular
|
||||
// expression that must match the string representation of the fact,
|
||||
// fmt.Sprint(fact). For example:
|
||||
//
|
||||
// func panicf(format string, args interface{}) { // want panicf:"printfWrapper"
|
||||
//
|
||||
// Package facts are specified by the name "package" and appear on
|
||||
// line 1 of the first source file of the package.
|
||||
//
|
||||
// A single 'want' comment may contain a mixture of diagnostic and fact
|
||||
// expectations, including multiple facts about the same object:
|
||||
//
|
||||
// // want "diag" "diag2" x:"fact1" x:"fact2" y:"fact3"
|
||||
//
|
||||
// Unexpected diagnostics and facts, and unmatched expectations, are
|
||||
// reported as errors to the Testing.
|
||||
//
|
||||
// Run reports an error to the Testing if loading or analysis failed.
|
||||
// Run also returns a Result for each package for which analysis was
|
||||
// attempted, even if unsuccessful. It is safe for a test to ignore all
|
||||
// the results, but a test may use it to perform additional checks.
|
||||
func Run(t Testing, dir string, a *analysis.Analyzer, patterns ...string) []*Result {
|
||||
pkgs, err := loadPackages(dir, patterns...)
|
||||
if err != nil {
|
||||
t.Errorf("loading %s: %v", patterns, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
results := checker.TestAnalyzer(a, pkgs)
|
||||
for _, result := range results {
|
||||
if result.Err != nil {
|
||||
t.Errorf("error analyzing %s: %v", result.Pass, result.Err)
|
||||
} else {
|
||||
check(t, dir, result.Pass, result.Diagnostics, result.Facts)
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// A Result holds the result of applying an analyzer to a package.
|
||||
type Result = checker.TestAnalyzerResult
|
||||
|
||||
// loadPackages uses go/packages to load a specified packages (from source, with
|
||||
// dependencies) from dir, which is the root of a GOPATH-style project
|
||||
// tree. It returns an error if any package had an error, or the pattern
|
||||
// matched no packages.
|
||||
func loadPackages(dir string, patterns ...string) ([]*packages.Package, error) {
|
||||
// packages.Load loads the real standard library, not a minimal
|
||||
// fake version, which would be more efficient, especially if we
|
||||
// have many small tests that import, say, net/http.
|
||||
// However there is no easy way to make go/packages to consume
|
||||
// a list of packages we generate and then do the parsing and
|
||||
// typechecking, though this feature seems to be a recurring need.
|
||||
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.LoadAllSyntax,
|
||||
Dir: dir,
|
||||
Tests: true,
|
||||
Env: append(os.Environ(), "GOPATH="+dir, "GO111MODULE=off", "GOPROXY=off"),
|
||||
}
|
||||
pkgs, err := packages.Load(cfg, patterns...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Print errors but do not stop:
|
||||
// some Analyzers may be disposed to RunDespiteErrors.
|
||||
packages.PrintErrors(pkgs)
|
||||
|
||||
if len(pkgs) == 0 {
|
||||
return nil, fmt.Errorf("no packages matched %s", patterns)
|
||||
}
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
// check inspects an analysis pass on which the analysis has already
|
||||
// been run, and verifies that all reported diagnostics and facts match
|
||||
// specified by the contents of "// want ..." comments in the package's
|
||||
// source files, which must have been parsed with comments enabled.
|
||||
func check(t Testing, gopath string, pass *analysis.Pass, diagnostics []analysis.Diagnostic, facts map[types.Object][]analysis.Fact) {
|
||||
|
||||
type key struct {
|
||||
file string
|
||||
line int
|
||||
}
|
||||
|
||||
want := make(map[key][]expectation)
|
||||
|
||||
// processComment parses expectations out of comments.
|
||||
processComment := func(filename string, linenum int, text string) {
|
||||
text = strings.TrimSpace(text)
|
||||
|
||||
// Any comment starting with "want" is treated
|
||||
// as an expectation, even without following whitespace.
|
||||
if rest := strings.TrimPrefix(text, "want"); rest != text {
|
||||
expects, err := parseExpectations(rest)
|
||||
if err != nil {
|
||||
t.Errorf("%s:%d: in 'want' comment: %s", filename, linenum, err)
|
||||
return
|
||||
}
|
||||
if expects != nil {
|
||||
want[key{filename, linenum}] = expects
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract 'want' comments from Go files.
|
||||
for _, f := range pass.Files {
|
||||
for _, cgroup := range f.Comments {
|
||||
for _, c := range cgroup.List {
|
||||
|
||||
text := strings.TrimPrefix(c.Text, "//")
|
||||
if text == c.Text {
|
||||
continue // not a //-comment
|
||||
}
|
||||
|
||||
// Hack: treat a comment of the form "//...// want..."
|
||||
// as if it starts at 'want'.
|
||||
// This allows us to add comments on comments,
|
||||
// as required when testing the buildtag analyzer.
|
||||
if i := strings.Index(text, "// want"); i >= 0 {
|
||||
text = text[i+len("// "):]
|
||||
}
|
||||
|
||||
// It's tempting to compute the filename
|
||||
// once outside the loop, but it's
|
||||
// incorrect because it can change due
|
||||
// to //line directives.
|
||||
posn := pass.Fset.Position(c.Pos())
|
||||
filename := sanitize(gopath, posn.Filename)
|
||||
processComment(filename, posn.Line, text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract 'want' comments from non-Go files.
|
||||
// TODO(adonovan): we may need to handle //line directives.
|
||||
for _, filename := range pass.OtherFiles {
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
t.Errorf("can't read '// want' comments from %s: %v", filename, err)
|
||||
continue
|
||||
}
|
||||
filename := sanitize(gopath, filename)
|
||||
linenum := 0
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
linenum++
|
||||
if i := strings.Index(line, "//"); i >= 0 {
|
||||
line = line[i+len("//"):]
|
||||
processComment(filename, linenum, line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkMessage := func(posn token.Position, kind, name, message string) {
|
||||
posn.Filename = sanitize(gopath, posn.Filename)
|
||||
k := key{posn.Filename, posn.Line}
|
||||
expects := want[k]
|
||||
var unmatched []string
|
||||
for i, exp := range expects {
|
||||
if exp.kind == kind && exp.name == name {
|
||||
if exp.rx.MatchString(message) {
|
||||
// matched: remove the expectation.
|
||||
expects[i] = expects[len(expects)-1]
|
||||
expects = expects[:len(expects)-1]
|
||||
want[k] = expects
|
||||
return
|
||||
}
|
||||
unmatched = append(unmatched, fmt.Sprintf("%q", exp.rx))
|
||||
}
|
||||
}
|
||||
if unmatched == nil {
|
||||
t.Errorf("%v: unexpected %s: %v", posn, kind, message)
|
||||
} else {
|
||||
t.Errorf("%v: %s %q does not match pattern %s",
|
||||
posn, kind, message, strings.Join(unmatched, " or "))
|
||||
}
|
||||
}
|
||||
|
||||
// Check the diagnostics match expectations.
|
||||
for _, f := range diagnostics {
|
||||
posn := pass.Fset.Position(f.Pos)
|
||||
checkMessage(posn, "diagnostic", "", f.Message)
|
||||
}
|
||||
|
||||
// Check the facts match expectations.
|
||||
// Report errors in lexical order for determinism.
|
||||
// (It's only deterministic within each file, not across files,
|
||||
// because go/packages does not guarantee file.Pos is ascending
|
||||
// across the files of a single compilation unit.)
|
||||
var objects []types.Object
|
||||
for obj := range facts {
|
||||
objects = append(objects, obj)
|
||||
}
|
||||
sort.Slice(objects, func(i, j int) bool {
|
||||
return objects[i].Pos() < objects[j].Pos()
|
||||
})
|
||||
for _, obj := range objects {
|
||||
var posn token.Position
|
||||
var name string
|
||||
if obj != nil {
|
||||
// Object facts are reported on the declaring line.
|
||||
name = obj.Name()
|
||||
posn = pass.Fset.Position(obj.Pos())
|
||||
} else {
|
||||
// Package facts are reported at the start of the file.
|
||||
name = "package"
|
||||
posn = pass.Fset.Position(pass.Files[0].Pos())
|
||||
posn.Line = 1
|
||||
}
|
||||
|
||||
for _, fact := range facts[obj] {
|
||||
checkMessage(posn, "fact", name, fmt.Sprint(fact))
|
||||
}
|
||||
}
|
||||
|
||||
// Reject surplus expectations.
|
||||
//
|
||||
// Sometimes an Analyzer reports two similar diagnostics on a
|
||||
// line with only one expectation. The reader may be confused by
|
||||
// the error message.
|
||||
// TODO(adonovan): print a better error:
|
||||
// "got 2 diagnostics here; each one needs its own expectation".
|
||||
var surplus []string
|
||||
for key, expects := range want {
|
||||
for _, exp := range expects {
|
||||
err := fmt.Sprintf("%s:%d: no %s was reported matching %q", key.file, key.line, exp.kind, exp.rx)
|
||||
surplus = append(surplus, err)
|
||||
}
|
||||
}
|
||||
sort.Strings(surplus)
|
||||
for _, err := range surplus {
|
||||
t.Errorf("%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
type expectation struct {
|
||||
kind string // either "fact" or "diagnostic"
|
||||
name string // name of object to which fact belongs, or "package" ("fact" only)
|
||||
rx *regexp.Regexp
|
||||
}
|
||||
|
||||
func (ex expectation) String() string {
|
||||
return fmt.Sprintf("%s %s:%q", ex.kind, ex.name, ex.rx) // for debugging
|
||||
}
|
||||
|
||||
// parseExpectations parses the content of a "// want ..." comment
|
||||
// and returns the expections, a mixture of diagnostics ("rx") and
|
||||
// facts (name:"rx").
|
||||
func parseExpectations(text string) ([]expectation, error) {
|
||||
var scanErr string
|
||||
sc := new(scanner.Scanner).Init(strings.NewReader(text))
|
||||
sc.Error = func(s *scanner.Scanner, msg string) {
|
||||
scanErr = msg // e.g. bad string escape
|
||||
}
|
||||
sc.Mode = scanner.ScanIdents | scanner.ScanStrings | scanner.ScanRawStrings
|
||||
|
||||
scanRegexp := func(tok rune) (*regexp.Regexp, error) {
|
||||
if tok != scanner.String && tok != scanner.RawString {
|
||||
return nil, fmt.Errorf("got %s, want regular expression",
|
||||
scanner.TokenString(tok))
|
||||
}
|
||||
pattern, _ := strconv.Unquote(sc.TokenText()) // can't fail
|
||||
return regexp.Compile(pattern)
|
||||
}
|
||||
|
||||
var expects []expectation
|
||||
for {
|
||||
tok := sc.Scan()
|
||||
switch tok {
|
||||
case scanner.String, scanner.RawString:
|
||||
rx, err := scanRegexp(tok)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
expects = append(expects, expectation{"diagnostic", "", rx})
|
||||
|
||||
case scanner.Ident:
|
||||
name := sc.TokenText()
|
||||
tok = sc.Scan()
|
||||
if tok != ':' {
|
||||
return nil, fmt.Errorf("got %s after %s, want ':'",
|
||||
scanner.TokenString(tok), name)
|
||||
}
|
||||
tok = sc.Scan()
|
||||
rx, err := scanRegexp(tok)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
expects = append(expects, expectation{"fact", name, rx})
|
||||
|
||||
case scanner.EOF:
|
||||
if scanErr != "" {
|
||||
return nil, fmt.Errorf("%s", scanErr)
|
||||
}
|
||||
return expects, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected %s", scanner.TokenString(tok))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sanitize removes the GOPATH portion of the filename,
|
||||
// typically a gnarly /tmp directory, and returns the rest.
|
||||
func sanitize(gopath, filename string) string {
|
||||
prefix := gopath + string(os.PathSeparator) + "src" + string(os.PathSeparator)
|
||||
return filepath.ToSlash(strings.TrimPrefix(filename, prefix))
|
||||
}
|
||||
93
vendor/golang.org/x/tools/go/analysis/analysistest/analysistest_test.go
generated
vendored
Normal file
93
vendor/golang.org/x/tools/go/analysis/analysistest/analysistest_test.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
package analysistest_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
"golang.org/x/tools/go/analysis/passes/findcall"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// This test currently requires GOPATH mode.
|
||||
// Explicitly disabling module mode should suffix, but
|
||||
// we'll also turn off GOPROXY just for good measure.
|
||||
if err := os.Setenv("GO111MODULE", "off"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := os.Setenv("GOPROXY", "off"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestTheTest tests the analysistest testing infrastructure.
|
||||
func TestTheTest(t *testing.T) {
|
||||
// We'll simulate a partly failing test of the findcall analysis,
|
||||
// which (by default) reports calls to functions named 'println'.
|
||||
findcall.Analyzer.Flags.Set("name", "println")
|
||||
|
||||
filemap := map[string]string{"a/b.go": `package main
|
||||
|
||||
func main() {
|
||||
// The expectation is ill-formed:
|
||||
print() // want: "diagnostic"
|
||||
print() // want foo"fact"
|
||||
print() // want foo:
|
||||
print() // want "\xZZ scan error"
|
||||
|
||||
// A dignostic is reported at this line, but the expectation doesn't match:
|
||||
println("hello, world") // want "wrong expectation text"
|
||||
|
||||
// An unexpected diagnostic is reported at this line:
|
||||
println() // trigger an unexpected diagnostic
|
||||
|
||||
// No diagnostic is reported at this line:
|
||||
print() // want "unsatisfied expectation"
|
||||
|
||||
// OK
|
||||
println("hello, world") // want "call of println"
|
||||
|
||||
// OK (multiple expectations on same line)
|
||||
println(); println() // want "call of println(...)" "call of println(...)"
|
||||
}
|
||||
|
||||
// OK (facts and diagnostics on same line)
|
||||
func println(...interface{}) { println() } // want println:"found" "call of println(...)"
|
||||
|
||||
`}
|
||||
dir, cleanup, err := analysistest.WriteFiles(filemap)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
var got []string
|
||||
t2 := errorfunc(func(s string) { got = append(got, s) }) // a fake *testing.T
|
||||
analysistest.Run(t2, dir, findcall.Analyzer, "a")
|
||||
|
||||
want := []string{
|
||||
`a/b.go:5: in 'want' comment: unexpected ":"`,
|
||||
`a/b.go:6: in 'want' comment: got String after foo, want ':'`,
|
||||
`a/b.go:7: in 'want' comment: got EOF, want regular expression`,
|
||||
`a/b.go:8: in 'want' comment: illegal char escape`,
|
||||
`a/b.go:11:9: diagnostic "call of println(...)" does not match pattern "wrong expectation text"`,
|
||||
`a/b.go:14:9: unexpected diagnostic: call of println(...)`,
|
||||
`a/b.go:11: no diagnostic was reported matching "wrong expectation text"`,
|
||||
`a/b.go:17: no diagnostic was reported matching "unsatisfied expectation"`,
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("got:\n%s\nwant:\n%s",
|
||||
strings.Join(got, "\n"),
|
||||
strings.Join(want, "\n"))
|
||||
}
|
||||
}
|
||||
|
||||
type errorfunc func(string)
|
||||
|
||||
func (f errorfunc) Errorf(format string, args ...interface{}) {
|
||||
f(fmt.Sprintf(format, args...))
|
||||
}
|
||||
74
vendor/golang.org/x/tools/go/analysis/cmd/vet-lite/main.go
generated
vendored
Normal file
74
vendor/golang.org/x/tools/go/analysis/cmd/vet-lite/main.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
// The vet-lite command is a driver for static checkers conforming to
|
||||
// the golang.org/x/tools/go/analysis API. It must be run by go vet:
|
||||
//
|
||||
// $ go vet -vettool=$(which vet-lite)
|
||||
//
|
||||
// For a checker also capable of running standalone, use multichecker.
|
||||
package main
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/go/analysis/unitchecker"
|
||||
|
||||
"golang.org/x/tools/go/analysis/passes/asmdecl"
|
||||
"golang.org/x/tools/go/analysis/passes/assign"
|
||||
"golang.org/x/tools/go/analysis/passes/atomic"
|
||||
"golang.org/x/tools/go/analysis/passes/bools"
|
||||
"golang.org/x/tools/go/analysis/passes/buildtag"
|
||||
"golang.org/x/tools/go/analysis/passes/cgocall"
|
||||
"golang.org/x/tools/go/analysis/passes/composite"
|
||||
"golang.org/x/tools/go/analysis/passes/copylock"
|
||||
"golang.org/x/tools/go/analysis/passes/httpresponse"
|
||||
"golang.org/x/tools/go/analysis/passes/loopclosure"
|
||||
"golang.org/x/tools/go/analysis/passes/lostcancel"
|
||||
"golang.org/x/tools/go/analysis/passes/nilfunc"
|
||||
"golang.org/x/tools/go/analysis/passes/printf"
|
||||
"golang.org/x/tools/go/analysis/passes/shift"
|
||||
"golang.org/x/tools/go/analysis/passes/stdmethods"
|
||||
"golang.org/x/tools/go/analysis/passes/structtag"
|
||||
"golang.org/x/tools/go/analysis/passes/tests"
|
||||
"golang.org/x/tools/go/analysis/passes/unmarshal"
|
||||
"golang.org/x/tools/go/analysis/passes/unreachable"
|
||||
"golang.org/x/tools/go/analysis/passes/unsafeptr"
|
||||
"golang.org/x/tools/go/analysis/passes/unusedresult"
|
||||
)
|
||||
|
||||
// Legacy vet had the concept of "experimental" checkers. There
|
||||
// was exactly one, shadow, and it had to be explicitly enabled
|
||||
// by the -shadow flag, which would of course disable all the
|
||||
// other tristate flags, requiring the -all flag to reenable them.
|
||||
// (By itself, -all did not enable all checkers.)
|
||||
// The -all flag is no longer needed, so it is a no-op.
|
||||
//
|
||||
// The shadow analyzer has been removed from the suite,
|
||||
// but can be run using these additional commands:
|
||||
// $ go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
|
||||
// $ go vet -vettool=$(which shadow)
|
||||
// Alternatively, one could build a multichecker containing all
|
||||
// the desired checks (vet's suite + shadow) and run it in a
|
||||
// single "go vet" command.
|
||||
|
||||
func main() {
|
||||
unitchecker.Main(
|
||||
asmdecl.Analyzer,
|
||||
assign.Analyzer,
|
||||
atomic.Analyzer,
|
||||
bools.Analyzer,
|
||||
buildtag.Analyzer,
|
||||
cgocall.Analyzer,
|
||||
composite.Analyzer,
|
||||
copylock.Analyzer,
|
||||
httpresponse.Analyzer,
|
||||
loopclosure.Analyzer,
|
||||
lostcancel.Analyzer,
|
||||
nilfunc.Analyzer,
|
||||
printf.Analyzer,
|
||||
shift.Analyzer,
|
||||
stdmethods.Analyzer,
|
||||
structtag.Analyzer,
|
||||
tests.Analyzer,
|
||||
unmarshal.Analyzer,
|
||||
unreachable.Analyzer,
|
||||
unsafeptr.Analyzer,
|
||||
unusedresult.Analyzer,
|
||||
)
|
||||
}
|
||||
33
vendor/golang.org/x/tools/go/analysis/cmd/vet/README
generated
vendored
Normal file
33
vendor/golang.org/x/tools/go/analysis/cmd/vet/README
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
Vet is a tool that checks correctness of Go programs. It runs a suite of tests,
|
||||
each tailored to check for a particular class of errors. Examples include incorrect
|
||||
Printf format verbs and malformed build tags.
|
||||
|
||||
Over time many checks have been added to vet's suite, but many more have been
|
||||
rejected as not appropriate for the tool. The criteria applied when selecting which
|
||||
checks to add are:
|
||||
|
||||
Correctness:
|
||||
|
||||
Vet's checks are about correctness, not style. A vet check must identify real or
|
||||
potential bugs that could cause incorrect compilation or execution. A check that
|
||||
only identifies stylistic points or alternative correct approaches to a situation
|
||||
is not acceptable.
|
||||
|
||||
Frequency:
|
||||
|
||||
Vet is run every day by many programmers, often as part of every compilation or
|
||||
submission. The cost in execution time is considerable, especially in aggregate,
|
||||
so checks must be likely enough to find real problems that they are worth the
|
||||
overhead of the added check. A new check that finds only a handful of problems
|
||||
across all existing programs, even if the problem is significant, is not worth
|
||||
adding to the suite everyone runs daily.
|
||||
|
||||
Precision:
|
||||
|
||||
Most of vet's checks are heuristic and can generate both false positives (flagging
|
||||
correct programs) and false negatives (not flagging incorrect ones). The rate of
|
||||
both these failures must be very small. A check that is too noisy will be ignored
|
||||
by the programmer overwhelmed by the output; a check that misses too many of the
|
||||
cases it's looking for will give a false sense of security. Neither is acceptable.
|
||||
A vet check must be accurate enough that everything it reports is worth examining,
|
||||
and complete enough to encourage real confidence.
|
||||
80
vendor/golang.org/x/tools/go/analysis/cmd/vet/vet.go
generated
vendored
Normal file
80
vendor/golang.org/x/tools/go/analysis/cmd/vet/vet.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// The vet command is a static checker for Go programs. It has pluggable
|
||||
// analyzers defined using the golang.org/x/tools/go/analysis API, and
|
||||
// using the golang.org/x/tools/go/packages API to load packages in any
|
||||
// build system.
|
||||
//
|
||||
// Each analyzer flag name is preceded by the analyzer name: -NAME.flag.
|
||||
// In addition, the -NAME flag itself controls whether the
|
||||
// diagnostics of that analyzer are displayed. (A disabled analyzer may yet
|
||||
// be run if it is required by some other analyzer that is enabled.)
|
||||
package main
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/go/analysis/multichecker"
|
||||
|
||||
// analysis plug-ins
|
||||
"golang.org/x/tools/go/analysis/passes/asmdecl"
|
||||
"golang.org/x/tools/go/analysis/passes/assign"
|
||||
"golang.org/x/tools/go/analysis/passes/atomic"
|
||||
"golang.org/x/tools/go/analysis/passes/bools"
|
||||
"golang.org/x/tools/go/analysis/passes/buildtag"
|
||||
"golang.org/x/tools/go/analysis/passes/cgocall"
|
||||
"golang.org/x/tools/go/analysis/passes/composite"
|
||||
"golang.org/x/tools/go/analysis/passes/copylock"
|
||||
"golang.org/x/tools/go/analysis/passes/httpresponse"
|
||||
"golang.org/x/tools/go/analysis/passes/loopclosure"
|
||||
"golang.org/x/tools/go/analysis/passes/lostcancel"
|
||||
"golang.org/x/tools/go/analysis/passes/nilfunc"
|
||||
"golang.org/x/tools/go/analysis/passes/nilness"
|
||||
"golang.org/x/tools/go/analysis/passes/printf"
|
||||
"golang.org/x/tools/go/analysis/passes/shift"
|
||||
"golang.org/x/tools/go/analysis/passes/stdmethods"
|
||||
"golang.org/x/tools/go/analysis/passes/structtag"
|
||||
"golang.org/x/tools/go/analysis/passes/tests"
|
||||
"golang.org/x/tools/go/analysis/passes/unmarshal"
|
||||
"golang.org/x/tools/go/analysis/passes/unreachable"
|
||||
"golang.org/x/tools/go/analysis/passes/unsafeptr"
|
||||
"golang.org/x/tools/go/analysis/passes/unusedresult"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// This suite of analyzers is applied to all code
|
||||
// in GOROOT by GOROOT/src/cmd/vet/all. When adding
|
||||
// a new analyzer, update the whitelist used by vet/all,
|
||||
// or change its vet command to disable the new analyzer.
|
||||
multichecker.Main(
|
||||
// the traditional vet suite:
|
||||
asmdecl.Analyzer,
|
||||
assign.Analyzer,
|
||||
atomic.Analyzer,
|
||||
bools.Analyzer,
|
||||
buildtag.Analyzer,
|
||||
cgocall.Analyzer,
|
||||
composite.Analyzer,
|
||||
copylock.Analyzer,
|
||||
httpresponse.Analyzer,
|
||||
loopclosure.Analyzer,
|
||||
lostcancel.Analyzer,
|
||||
nilfunc.Analyzer,
|
||||
printf.Analyzer,
|
||||
shift.Analyzer,
|
||||
stdmethods.Analyzer,
|
||||
structtag.Analyzer,
|
||||
tests.Analyzer,
|
||||
unmarshal.Analyzer,
|
||||
unreachable.Analyzer,
|
||||
unsafeptr.Analyzer,
|
||||
unusedresult.Analyzer,
|
||||
|
||||
// for debugging:
|
||||
// findcall.Analyzer,
|
||||
// pkgfact.Analyzer,
|
||||
|
||||
// uses SSA:
|
||||
nilness.Analyzer,
|
||||
)
|
||||
}
|
||||
340
vendor/golang.org/x/tools/go/analysis/doc.go
generated
vendored
Normal file
340
vendor/golang.org/x/tools/go/analysis/doc.go
generated
vendored
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
|
||||
The analysis package defines the interface between a modular static
|
||||
analysis and an analysis driver program.
|
||||
|
||||
|
||||
THIS INTERFACE IS EXPERIMENTAL AND SUBJECT TO CHANGE.
|
||||
We aim to finalize it by November 2018.
|
||||
|
||||
Background
|
||||
|
||||
A static analysis is a function that inspects a package of Go code and
|
||||
reports a set of diagnostics (typically mistakes in the code), and
|
||||
perhaps produces other results as well, such as suggested refactorings
|
||||
or other facts. An analysis that reports mistakes is informally called a
|
||||
"checker". For example, the printf checker reports mistakes in
|
||||
fmt.Printf format strings.
|
||||
|
||||
A "modular" analysis is one that inspects one package at a time but can
|
||||
save information from a lower-level package and use it when inspecting a
|
||||
higher-level package, analogous to separate compilation in a toolchain.
|
||||
The printf checker is modular: when it discovers that a function such as
|
||||
log.Fatalf delegates to fmt.Printf, it records this fact, and checks
|
||||
calls to that function too, including calls made from another package.
|
||||
|
||||
By implementing a common interface, checkers from a variety of sources
|
||||
can be easily selected, incorporated, and reused in a wide range of
|
||||
driver programs including command-line tools (such as vet), text editors and
|
||||
IDEs, build and test systems (such as go build, Bazel, or Buck), test
|
||||
frameworks, code review tools, code-base indexers (such as SourceGraph),
|
||||
documentation viewers (such as godoc), batch pipelines for large code
|
||||
bases, and so on.
|
||||
|
||||
|
||||
Analyzer
|
||||
|
||||
The primary type in the API is Analyzer. An Analyzer statically
|
||||
describes an analysis function: its name, documentation, flags,
|
||||
relationship to other analyzers, and of course, its logic.
|
||||
|
||||
To define an analysis, a user declares a (logically constant) variable
|
||||
of type Analyzer. Here is a typical example from one of the analyzers in
|
||||
the go/analysis/passes/ subdirectory:
|
||||
|
||||
package unusedresult
|
||||
|
||||
var Analyzer = &analysis.Analyzer{
|
||||
Name: "unusedresult",
|
||||
Doc: "check for unused results of calls to some functions",
|
||||
Run: run,
|
||||
...
|
||||
}
|
||||
|
||||
func run(pass *analysis.Pass) (interface{}, error) {
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
An analysis driver is a program such as vet that runs a set of
|
||||
analyses and prints the diagnostics that they report.
|
||||
The driver program must import the list of Analyzers it needs.
|
||||
Typically each Analyzer resides in a separate package.
|
||||
To add a new Analyzer to an existing driver, add another item to the list:
|
||||
|
||||
import ( "unusedresult"; "nilness"; "printf" )
|
||||
|
||||
var analyses = []*analysis.Analyzer{
|
||||
unusedresult.Analyzer,
|
||||
nilness.Analyzer,
|
||||
printf.Analyzer,
|
||||
}
|
||||
|
||||
A driver may use the name, flags, and documentation to provide on-line
|
||||
help that describes the analyses its performs.
|
||||
The doc comment contains a brief one-line summary,
|
||||
optionally followed by paragraphs of explanation.
|
||||
The vet command, shown below, is an example of a driver that runs
|
||||
multiple analyzers. It is based on the multichecker package
|
||||
(see the "Standalone commands" section for details).
|
||||
|
||||
$ go build golang.org/x/tools/go/analysis/cmd/vet
|
||||
$ ./vet help
|
||||
vet is a tool for static analysis of Go programs.
|
||||
|
||||
Usage: vet [-flag] [package]
|
||||
|
||||
Registered analyzers:
|
||||
|
||||
asmdecl report mismatches between assembly files and Go declarations
|
||||
assign check for useless assignments
|
||||
atomic check for common mistakes using the sync/atomic package
|
||||
...
|
||||
unusedresult check for unused results of calls to some functions
|
||||
|
||||
$ ./vet help unusedresult
|
||||
unusedresult: check for unused results of calls to some functions
|
||||
|
||||
Analyzer flags:
|
||||
|
||||
-unusedresult.funcs value
|
||||
comma-separated list of functions whose results must be used (default Error,String)
|
||||
-unusedresult.stringmethods value
|
||||
comma-separated list of names of methods of type func() string whose results must be used
|
||||
|
||||
Some functions like fmt.Errorf return a result and have no side effects,
|
||||
so it is always a mistake to discard the result. This analyzer reports
|
||||
calls to certain functions in which the result of the call is ignored.
|
||||
|
||||
The set of functions may be controlled using flags.
|
||||
|
||||
The Analyzer type has more fields besides those shown above:
|
||||
|
||||
type Analyzer struct {
|
||||
Name string
|
||||
Doc string
|
||||
Flags flag.FlagSet
|
||||
Run func(*Pass) (interface{}, error)
|
||||
RunDespiteErrors bool
|
||||
ResultType reflect.Type
|
||||
Requires []*Analyzer
|
||||
FactTypes []Fact
|
||||
}
|
||||
|
||||
The Flags field declares a set of named (global) flag variables that
|
||||
control analysis behavior. Unlike vet, analysis flags are not declared
|
||||
directly in the command line FlagSet; it is up to the driver to set the
|
||||
flag variables. A driver for a single analysis, a, might expose its flag
|
||||
f directly on the command line as -f, whereas a driver for multiple
|
||||
analyses might prefix the flag name by the analysis name (-a.f) to avoid
|
||||
ambiguity. An IDE might expose the flags through a graphical interface,
|
||||
and a batch pipeline might configure them from a config file.
|
||||
See the "findcall" analyzer for an example of flags in action.
|
||||
|
||||
The RunDespiteErrors flag indicates whether the analysis is equipped to
|
||||
handle ill-typed code. If not, the driver will skip the analysis if
|
||||
there were parse or type errors.
|
||||
The optional ResultType field specifies the type of the result value
|
||||
computed by this analysis and made available to other analyses.
|
||||
The Requires field specifies a list of analyses upon which
|
||||
this one depends and whose results it may access, and it constrains the
|
||||
order in which a driver may run analyses.
|
||||
The FactTypes field is discussed in the section on Modularity.
|
||||
The analysis package provides a Validate function to perform basic
|
||||
sanity checks on an Analyzer, such as that its Requires graph is
|
||||
acyclic, its fact and result types are unique, and so on.
|
||||
|
||||
Finally, the Run field contains a function to be called by the driver to
|
||||
execute the analysis on a single package. The driver passes it an
|
||||
instance of the Pass type.
|
||||
|
||||
|
||||
Pass
|
||||
|
||||
A Pass describes a single unit of work: the application of a particular
|
||||
Analyzer to a particular package of Go code.
|
||||
The Pass provides information to the Analyzer's Run function about the
|
||||
package being analyzed, and provides operations to the Run function for
|
||||
reporting diagnostics and other information back to the driver.
|
||||
|
||||
type Pass struct {
|
||||
Fset *token.FileSet
|
||||
Files []*ast.File
|
||||
OtherFiles []string
|
||||
Pkg *types.Package
|
||||
TypesInfo *types.Info
|
||||
ResultOf map[*Analyzer]interface{}
|
||||
Report func(Diagnostic)
|
||||
...
|
||||
}
|
||||
|
||||
The Fset, Files, Pkg, and TypesInfo fields provide the syntax trees,
|
||||
type information, and source positions for a single package of Go code.
|
||||
|
||||
The OtherFiles field provides the names, but not the contents, of non-Go
|
||||
files such as assembly that are part of this package. See the "asmdecl"
|
||||
or "buildtags" analyzers for examples of loading non-Go files and report
|
||||
diagnostics against them.
|
||||
|
||||
The ResultOf field provides the results computed by the analyzers
|
||||
required by this one, as expressed in its Analyzer.Requires field. The
|
||||
driver runs the required analyzers first and makes their results
|
||||
available in this map. Each Analyzer must return a value of the type
|
||||
described in its Analyzer.ResultType field.
|
||||
For example, the "ctrlflow" analyzer returns a *ctrlflow.CFGs, which
|
||||
provides a control-flow graph for each function in the package (see
|
||||
golang.org/x/tools/go/cfg); the "inspect" analyzer returns a value that
|
||||
enables other Analyzers to traverse the syntax trees of the package more
|
||||
efficiently; and the "buildssa" analyzer constructs an SSA-form
|
||||
intermediate representation.
|
||||
Each of these Analyzers extends the capabilities of later Analyzers
|
||||
without adding a dependency to the core API, so an analysis tool pays
|
||||
only for the extensions it needs.
|
||||
|
||||
The Report function emits a diagnostic, a message associated with a
|
||||
source position. For most analyses, diagnostics are their primary
|
||||
result.
|
||||
For convenience, Pass provides a helper method, Reportf, to report a new
|
||||
diagnostic by formatting a string.
|
||||
Diagnostic is defined as:
|
||||
|
||||
type Diagnostic struct {
|
||||
Pos token.Pos
|
||||
Category string // optional
|
||||
Message string
|
||||
}
|
||||
|
||||
The optional Category field is a short identifier that classifies the
|
||||
kind of message when an analysis produces several kinds of diagnostic.
|
||||
|
||||
Most Analyzers inspect typed Go syntax trees, but a few, such as asmdecl
|
||||
and buildtag, inspect the raw text of Go source files or even non-Go
|
||||
files such as assembly. To report a diagnostic against a line of a
|
||||
raw text file, use the following sequence:
|
||||
|
||||
content, err := ioutil.ReadFile(filename)
|
||||
if err != nil { ... }
|
||||
tf := fset.AddFile(filename, -1, len(content))
|
||||
tf.SetLinesForContent(content)
|
||||
...
|
||||
pass.Reportf(tf.LineStart(line), "oops")
|
||||
|
||||
|
||||
Modular analysis with Facts
|
||||
|
||||
To improve efficiency and scalability, large programs are routinely
|
||||
built using separate compilation: units of the program are compiled
|
||||
separately, and recompiled only when one of their dependencies changes;
|
||||
independent modules may be compiled in parallel. The same technique may
|
||||
be applied to static analyses, for the same benefits. Such analyses are
|
||||
described as "modular".
|
||||
|
||||
A compiler’s type checker is an example of a modular static analysis.
|
||||
Many other checkers we would like to apply to Go programs can be
|
||||
understood as alternative or non-standard type systems. For example,
|
||||
vet's printf checker infers whether a function has the "printf wrapper"
|
||||
type, and it applies stricter checks to calls of such functions. In
|
||||
addition, it records which functions are printf wrappers for use by
|
||||
later analysis units to identify other printf wrappers by induction.
|
||||
A result such as “f is a printf wrapper” that is not interesting by
|
||||
itself but serves as a stepping stone to an interesting result (such as
|
||||
a diagnostic) is called a "fact".
|
||||
|
||||
The analysis API allows an analysis to define new types of facts, to
|
||||
associate facts of these types with objects (named entities) declared
|
||||
within the current package, or with the package as a whole, and to query
|
||||
for an existing fact of a given type associated with an object or
|
||||
package.
|
||||
|
||||
An Analyzer that uses facts must declare their types:
|
||||
|
||||
var Analyzer = &analysis.Analyzer{
|
||||
Name: "printf",
|
||||
FactTypes: []reflect.Type{reflect.TypeOf(new(isWrapper))},
|
||||
...
|
||||
}
|
||||
|
||||
type isWrapper struct{} // => *types.Func f “is a printf wrapper”
|
||||
|
||||
A driver program ensures that facts for a pass’s dependencies are
|
||||
generated before analyzing the pass and are responsible for propagating
|
||||
facts between from one pass to another, possibly across address spaces.
|
||||
Consequently, Facts must be serializable. The API requires that drivers
|
||||
use the gob encoding, an efficient, robust, self-describing binary
|
||||
protocol. A fact type may implement the GobEncoder/GobDecoder interfaces
|
||||
if the default encoding is unsuitable. Facts should be stateless.
|
||||
|
||||
The Pass type has functions to import and export facts,
|
||||
associated either with an object or with a package:
|
||||
|
||||
type Pass struct {
|
||||
...
|
||||
ExportObjectFact func(types.Object, Fact)
|
||||
ImportObjectFact func(types.Object, Fact) bool
|
||||
|
||||
ExportPackageFact func(fact Fact)
|
||||
ImportPackageFact func(*types.Package, Fact) bool
|
||||
}
|
||||
|
||||
An Analyzer may only export facts associated with the current package or
|
||||
its objects, though it may import facts from any package or object that
|
||||
is an import dependency of the current package.
|
||||
|
||||
Conceptually, ExportObjectFact(obj, fact) inserts fact into a hidden map keyed by
|
||||
the pair (obj, TypeOf(fact)), and the ImportObjectFact function
|
||||
retrieves the entry from this map and copies its value into the variable
|
||||
pointed to by fact. This scheme assumes that the concrete type of fact
|
||||
is a pointer; this assumption is checked by the Validate function.
|
||||
See the "printf" analyzer for an example of object facts in action.
|
||||
|
||||
Some driver implementations (such as those based on Bazel and Blaze) do
|
||||
not currently apply analyzers to packages of the standard library.
|
||||
Therefore, for best results, analyzer authors should not rely on
|
||||
analysis facts being available for standard packages.
|
||||
For example, although the printf checker is capable of deducing during
|
||||
analysis of the log package that log.Printf is a printf-wrapper,
|
||||
this fact is built in to the analyzer so that it correctly checks
|
||||
calls to log.Printf even when run in a driver that does not apply
|
||||
it to standard packages. We plan to remove this limitation in future.
|
||||
|
||||
|
||||
Testing an Analyzer
|
||||
|
||||
The analysistest subpackage provides utilities for testing an Analyzer.
|
||||
In a few lines of code, it is possible to run an analyzer on a package
|
||||
of testdata files and check that it reported all the expected
|
||||
diagnostics and facts (and no more). Expectations are expressed using
|
||||
"// want ..." comments in the input code.
|
||||
|
||||
|
||||
Standalone commands
|
||||
|
||||
Analyzers are provided in the form of packages that a driver program is
|
||||
expected to import. The vet command imports a set of several analyzers,
|
||||
but users may wish to define their own analysis commands that perform
|
||||
additional checks. To simplify the task of creating an analysis command,
|
||||
either for a single analyzer or for a whole suite, we provide the
|
||||
singlechecker and multichecker subpackages.
|
||||
|
||||
The singlechecker package provides the main function for a command that
|
||||
runs one analyzer. By convention, each analyzer such as
|
||||
go/passes/findcall should be accompanied by a singlechecker-based
|
||||
command such as go/analysis/passes/findcall/cmd/findcall, defined in its
|
||||
entirety as:
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/go/analysis/passes/findcall"
|
||||
"golang.org/x/tools/go/analysis/singlechecker"
|
||||
)
|
||||
|
||||
func main() { singlechecker.Main(findcall.Analyzer) }
|
||||
|
||||
A tool that provides multiple analyzers can use multichecker in a
|
||||
similar way, giving it the list of Analyzers.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
package analysis
|
||||
343
vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
generated
vendored
Normal file
343
vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
generated
vendored
Normal file
@@ -0,0 +1,343 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// Package analysisflags defines helpers for processing flags of
|
||||
// analysis driver tools.
|
||||
package analysisflags
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
// flags common to all {single,multi,unit}checkers.
|
||||
var (
|
||||
JSON = false // -json
|
||||
Context = -1 // -c=N: if N>0, display offending line plus N lines of context
|
||||
)
|
||||
|
||||
// Parse creates a flag for each of the analyzer's flags,
|
||||
// including (in multi mode) a flag named after the analyzer,
|
||||
// parses the flags, then filters and returns the list of
|
||||
// analyzers enabled by flags.
|
||||
func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
|
||||
// Connect each analysis flag to the command line as -analysis.flag.
|
||||
enabled := make(map[*analysis.Analyzer]*triState)
|
||||
for _, a := range analyzers {
|
||||
var prefix string
|
||||
|
||||
// Add -NAME flag to enable it.
|
||||
if multi {
|
||||
prefix = a.Name + "."
|
||||
|
||||
enable := new(triState)
|
||||
enableUsage := "enable " + a.Name + " analysis"
|
||||
flag.Var(enable, a.Name, enableUsage)
|
||||
enabled[a] = enable
|
||||
}
|
||||
|
||||
a.Flags.VisitAll(func(f *flag.Flag) {
|
||||
if !multi && flag.Lookup(f.Name) != nil {
|
||||
log.Printf("%s flag -%s would conflict with driver; skipping", a.Name, f.Name)
|
||||
return
|
||||
}
|
||||
|
||||
name := prefix + f.Name
|
||||
flag.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
// standard flags: -flags, -V.
|
||||
printflags := flag.Bool("flags", false, "print analyzer flags in JSON")
|
||||
addVersionFlag()
|
||||
|
||||
// flags common to all checkers
|
||||
flag.BoolVar(&JSON, "json", JSON, "emit JSON output")
|
||||
flag.IntVar(&Context, "c", Context, `display offending line with this many lines of context`)
|
||||
|
||||
// Add shims for legacy vet flags to enable existing
|
||||
// scripts that run vet to continue to work.
|
||||
_ = flag.Bool("source", false, "no effect (deprecated)")
|
||||
_ = flag.Bool("v", false, "no effect (deprecated)")
|
||||
_ = flag.Bool("all", false, "no effect (deprecated)")
|
||||
_ = flag.String("tags", "", "no effect (deprecated)")
|
||||
for old, new := range vetLegacyFlags {
|
||||
newFlag := flag.Lookup(new)
|
||||
if newFlag != nil && flag.Lookup(old) == nil {
|
||||
flag.Var(newFlag.Value, old, "deprecated alias for -"+new)
|
||||
}
|
||||
}
|
||||
|
||||
flag.Parse() // (ExitOnError)
|
||||
|
||||
// -flags: print flags so that go vet knows which ones are legitimate.
|
||||
if *printflags {
|
||||
printFlags()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// If any -NAME flag is true, run only those analyzers. Otherwise,
|
||||
// if any -NAME flag is false, run all but those analyzers.
|
||||
if multi {
|
||||
var hasTrue, hasFalse bool
|
||||
for _, ts := range enabled {
|
||||
switch *ts {
|
||||
case setTrue:
|
||||
hasTrue = true
|
||||
case setFalse:
|
||||
hasFalse = true
|
||||
}
|
||||
}
|
||||
|
||||
var keep []*analysis.Analyzer
|
||||
if hasTrue {
|
||||
for _, a := range analyzers {
|
||||
if *enabled[a] == setTrue {
|
||||
keep = append(keep, a)
|
||||
}
|
||||
}
|
||||
analyzers = keep
|
||||
} else if hasFalse {
|
||||
for _, a := range analyzers {
|
||||
if *enabled[a] != setFalse {
|
||||
keep = append(keep, a)
|
||||
}
|
||||
}
|
||||
analyzers = keep
|
||||
}
|
||||
}
|
||||
|
||||
return analyzers
|
||||
}
|
||||
|
||||
func printFlags() {
|
||||
type jsonFlag struct {
|
||||
Name string
|
||||
Bool bool
|
||||
Usage string
|
||||
}
|
||||
var flags []jsonFlag = nil
|
||||
flag.VisitAll(func(f *flag.Flag) {
|
||||
// Don't report {single,multi}checker debugging
|
||||
// flags as these have no effect on unitchecker
|
||||
// (as invoked by 'go vet').
|
||||
switch f.Name {
|
||||
case "debug", "cpuprofile", "memprofile", "trace":
|
||||
return
|
||||
}
|
||||
|
||||
b, ok := f.Value.(interface{ IsBoolFlag() bool })
|
||||
isBool := ok && b.IsBoolFlag()
|
||||
flags = append(flags, jsonFlag{f.Name, isBool, f.Usage})
|
||||
})
|
||||
data, err := json.MarshalIndent(flags, "", "\t")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
os.Stdout.Write(data)
|
||||
}
|
||||
|
||||
// addVersionFlag registers a -V flag that, if set,
|
||||
// prints the executable version and exits 0.
|
||||
//
|
||||
// It is a variable not a function to permit easy
|
||||
// overriding in the copy vendored in $GOROOT/src/cmd/vet:
|
||||
//
|
||||
// func init() { addVersionFlag = objabi.AddVersionFlag }
|
||||
var addVersionFlag = func() {
|
||||
flag.Var(versionFlag{}, "V", "print version and exit")
|
||||
}
|
||||
|
||||
// versionFlag minimally complies with the -V protocol required by "go vet".
|
||||
type versionFlag struct{}
|
||||
|
||||
func (versionFlag) IsBoolFlag() bool { return true }
|
||||
func (versionFlag) Get() interface{} { return nil }
|
||||
func (versionFlag) String() string { return "" }
|
||||
func (versionFlag) Set(s string) error {
|
||||
if s != "full" {
|
||||
log.Fatalf("unsupported flag value: -V=%s", s)
|
||||
}
|
||||
|
||||
// This replicates the miminal subset of
|
||||
// cmd/internal/objabi.AddVersionFlag, which is private to the
|
||||
// go tool yet forms part of our command-line interface.
|
||||
// TODO(adonovan): clarify the contract.
|
||||
|
||||
// Print the tool version so the build system can track changes.
|
||||
// Formats:
|
||||
// $progname version devel ... buildID=...
|
||||
// $progname version go1.9.1
|
||||
progname := os.Args[0]
|
||||
f, err := os.Open(progname)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
h := sha256.New()
|
||||
if _, err := io.Copy(h, f); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
f.Close()
|
||||
fmt.Printf("%s version devel comments-go-here buildID=%02x\n",
|
||||
progname, string(h.Sum(nil)))
|
||||
os.Exit(0)
|
||||
return nil
|
||||
}
|
||||
|
||||
// A triState is a boolean that knows whether
|
||||
// it has been set to either true or false.
|
||||
// It is used to identify whether a flag appears;
|
||||
// the standard boolean flag cannot
|
||||
// distinguish missing from unset.
|
||||
// It also satisfies flag.Value.
|
||||
type triState int
|
||||
|
||||
const (
|
||||
unset triState = iota
|
||||
setTrue
|
||||
setFalse
|
||||
)
|
||||
|
||||
func triStateFlag(name string, value triState, usage string) *triState {
|
||||
flag.Var(&value, name, usage)
|
||||
return &value
|
||||
}
|
||||
|
||||
// triState implements flag.Value, flag.Getter, and flag.boolFlag.
|
||||
// They work like boolean flags: we can say vet -printf as well as vet -printf=true
|
||||
func (ts *triState) Get() interface{} {
|
||||
return *ts == setTrue
|
||||
}
|
||||
|
||||
func (ts triState) isTrue() bool {
|
||||
return ts == setTrue
|
||||
}
|
||||
|
||||
func (ts *triState) Set(value string) error {
|
||||
b, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
// This error message looks poor but package "flag" adds
|
||||
// "invalid boolean value %q for -NAME: %s"
|
||||
return fmt.Errorf("want true or false")
|
||||
}
|
||||
if b {
|
||||
*ts = setTrue
|
||||
} else {
|
||||
*ts = setFalse
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ts *triState) String() string {
|
||||
switch *ts {
|
||||
case unset:
|
||||
return "true"
|
||||
case setTrue:
|
||||
return "true"
|
||||
case setFalse:
|
||||
return "false"
|
||||
}
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
func (ts triState) IsBoolFlag() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Legacy flag support
|
||||
|
||||
// vetLegacyFlags maps flags used by legacy vet to their corresponding
|
||||
// new names. The old names will continue to work.
|
||||
var vetLegacyFlags = map[string]string{
|
||||
// Analyzer name changes
|
||||
"bool": "bools",
|
||||
"buildtags": "buildtag",
|
||||
"methods": "stdmethods",
|
||||
"rangeloops": "loopclosure",
|
||||
|
||||
// Analyzer flags
|
||||
"compositewhitelist": "composites.whitelist",
|
||||
"printfuncs": "printf.funcs",
|
||||
"shadowstrict": "shadow.strict",
|
||||
"unusedfuncs": "unusedresult.funcs",
|
||||
"unusedstringmethods": "unusedresult.stringmethods",
|
||||
}
|
||||
|
||||
// ---- output helpers common to all drivers ----
|
||||
|
||||
// PrintPlain prints a diagnostic in plain text form,
|
||||
// with context specified by the -c flag.
|
||||
func PrintPlain(fset *token.FileSet, diag analysis.Diagnostic) {
|
||||
posn := fset.Position(diag.Pos)
|
||||
fmt.Fprintf(os.Stderr, "%s: %s\n", posn, diag.Message)
|
||||
|
||||
// -c=N: show offending line plus N lines of context.
|
||||
if Context >= 0 {
|
||||
data, _ := ioutil.ReadFile(posn.Filename)
|
||||
lines := strings.Split(string(data), "\n")
|
||||
for i := posn.Line - Context; i <= posn.Line+Context; i++ {
|
||||
if 1 <= i && i <= len(lines) {
|
||||
fmt.Fprintf(os.Stderr, "%d\t%s\n", i, lines[i-1])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A JSONTree is a mapping from package ID to analysis name to result.
|
||||
// Each result is either a jsonError or a list of jsonDiagnostic.
|
||||
type JSONTree map[string]map[string]interface{}
|
||||
|
||||
// Add adds the result of analysis 'name' on package 'id'.
|
||||
// The result is either a list of diagnostics or an error.
|
||||
func (tree JSONTree) Add(fset *token.FileSet, id, name string, diags []analysis.Diagnostic, err error) {
|
||||
var v interface{}
|
||||
if err != nil {
|
||||
type jsonError struct {
|
||||
Err string `json:"error"`
|
||||
}
|
||||
v = jsonError{err.Error()}
|
||||
} else if len(diags) > 0 {
|
||||
type jsonDiagnostic struct {
|
||||
Category string `json:"category,omitempty"`
|
||||
Posn string `json:"posn"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
var diagnostics []jsonDiagnostic
|
||||
for _, f := range diags {
|
||||
diagnostics = append(diagnostics, jsonDiagnostic{
|
||||
Category: f.Category,
|
||||
Posn: fset.Position(f.Pos).String(),
|
||||
Message: f.Message,
|
||||
})
|
||||
}
|
||||
v = diagnostics
|
||||
}
|
||||
if v != nil {
|
||||
m, ok := tree[id]
|
||||
if !ok {
|
||||
m = make(map[string]interface{})
|
||||
tree[id] = m
|
||||
}
|
||||
m[name] = v
|
||||
}
|
||||
}
|
||||
|
||||
func (tree JSONTree) Print() {
|
||||
data, err := json.MarshalIndent(tree, "", "\t")
|
||||
if err != nil {
|
||||
log.Panicf("internal error: JSON marshalling failed: %v", err)
|
||||
}
|
||||
fmt.Printf("%s\n", data)
|
||||
}
|
||||
67
vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags_test.go
generated
vendored
Normal file
67
vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags_test.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
package analysisflags_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/internal/analysisflags"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(analysisflags.Parse([]*analysis.Analyzer{
|
||||
{Name: "a1", Doc: "a1"},
|
||||
{Name: "a2", Doc: "a2"},
|
||||
{Name: "a3", Doc: "a3"},
|
||||
}, true))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// This test fork/execs the main function above.
|
||||
func TestExec(t *testing.T) {
|
||||
if runtime.GOOS != "linux" {
|
||||
t.Skipf("skipping fork/exec test on this platform")
|
||||
}
|
||||
|
||||
progname := os.Args[0]
|
||||
|
||||
if os.Getenv("ANALYSISFLAGS_CHILD") == "1" {
|
||||
// child process
|
||||
os.Args = strings.Fields(progname + " " + os.Getenv("FLAGS"))
|
||||
main()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
for _, test := range []struct {
|
||||
flags string
|
||||
want string
|
||||
}{
|
||||
{"", "[a1 a2 a3]"},
|
||||
{"-a1=0", "[a2 a3]"},
|
||||
{"-a1=1", "[a1]"},
|
||||
{"-a1", "[a1]"},
|
||||
{"-a1=1 -a3=1", "[a1 a3]"},
|
||||
{"-a1=1 -a3=0", "[a1]"},
|
||||
} {
|
||||
cmd := exec.Command(progname, "-test.run=TestExec")
|
||||
cmd.Env = append(os.Environ(), "ANALYSISFLAGS_CHILD=1", "FLAGS="+test.flags)
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("exec failed: %v; output=<<%s>>", err, output)
|
||||
}
|
||||
|
||||
got := strings.TrimSpace(string(output))
|
||||
if got != test.want {
|
||||
t.Errorf("got %s, want %s", got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
89
vendor/golang.org/x/tools/go/analysis/internal/analysisflags/help.go
generated
vendored
Normal file
89
vendor/golang.org/x/tools/go/analysis/internal/analysisflags/help.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
package analysisflags
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
)
|
||||
|
||||
const help = `PROGNAME is a tool for static analysis of Go programs.
|
||||
|
||||
PROGNAME examines Go source code and reports suspicious constructs,
|
||||
such as Printf calls whose arguments do not align with the format
|
||||
string. It uses heuristics that do not guarantee all reports are
|
||||
genuine problems, but it can find errors not caught by the compilers.
|
||||
`
|
||||
|
||||
// Help implements the help subcommand for a multichecker or vet-lite
|
||||
// style command. The optional args specify the analyzers to describe.
|
||||
// Help calls log.Fatal if no such analyzer exists.
|
||||
func Help(progname string, analyzers []*analysis.Analyzer, args []string) {
|
||||
// No args: show summary of all analyzers.
|
||||
if len(args) == 0 {
|
||||
fmt.Println(strings.Replace(help, "PROGNAME", progname, -1))
|
||||
fmt.Println("Registered analyzers:")
|
||||
fmt.Println()
|
||||
sort.Slice(analyzers, func(i, j int) bool {
|
||||
return analyzers[i].Name < analyzers[j].Name
|
||||
})
|
||||
for _, a := range analyzers {
|
||||
title := strings.Split(a.Doc, "\n\n")[0]
|
||||
fmt.Printf(" %-12s %s\n", a.Name, title)
|
||||
}
|
||||
fmt.Println("\nBy default all analyzers are run.")
|
||||
fmt.Println("To select specific analyzers, use the -NAME flag for each one,")
|
||||
fmt.Println(" or -NAME=false to run all analyzers not explicitly disabled.")
|
||||
|
||||
// Show only the core command-line flags.
|
||||
fmt.Println("\nCore flags:")
|
||||
fmt.Println()
|
||||
fs := flag.NewFlagSet("", flag.ExitOnError)
|
||||
flag.VisitAll(func(f *flag.Flag) {
|
||||
if !strings.Contains(f.Name, ".") {
|
||||
fs.Var(f.Value, f.Name, f.Usage)
|
||||
}
|
||||
})
|
||||
fs.PrintDefaults()
|
||||
|
||||
fmt.Printf("\nTo see details and flags of a specific analyzer, run '%s help name'.\n", progname)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Show help on specific analyzer(s).
|
||||
outer:
|
||||
for _, arg := range args {
|
||||
for _, a := range analyzers {
|
||||
if a.Name == arg {
|
||||
paras := strings.Split(a.Doc, "\n\n")
|
||||
title := paras[0]
|
||||
fmt.Printf("%s: %s\n", a.Name, title)
|
||||
|
||||
// Show only the flags relating to this analysis,
|
||||
// properly prefixed.
|
||||
first := true
|
||||
fs := flag.NewFlagSet(a.Name, flag.ExitOnError)
|
||||
a.Flags.VisitAll(func(f *flag.Flag) {
|
||||
if first {
|
||||
first = false
|
||||
fmt.Println("\nAnalyzer flags:")
|
||||
fmt.Println()
|
||||
}
|
||||
fs.Var(f.Value, a.Name+"."+f.Name, f.Usage)
|
||||
})
|
||||
fs.PrintDefaults()
|
||||
|
||||
if len(paras) > 1 {
|
||||
fmt.Printf("\n%s\n", strings.Join(paras[1:], "\n\n"))
|
||||
}
|
||||
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
log.Fatalf("Analyzer %q not registered", arg)
|
||||
}
|
||||
}
|
||||
701
vendor/golang.org/x/tools/go/analysis/internal/checker/checker.go
generated
vendored
Normal file
701
vendor/golang.org/x/tools/go/analysis/internal/checker/checker.go
generated
vendored
Normal file
@@ -0,0 +1,701 @@
|
||||
// Package checker defines the implementation of the checker commands.
|
||||
// The same code drives the multi-analysis driver, the single-analysis
|
||||
// driver that is conventionally provided for convenience along with
|
||||
// each analysis package, and the test driver.
|
||||
package checker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"runtime/trace"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/internal/analysisflags"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
var (
|
||||
// Debug is a set of single-letter flags:
|
||||
//
|
||||
// f show [f]acts as they are created
|
||||
// p disable [p]arallel execution of analyzers
|
||||
// s do additional [s]anity checks on fact types and serialization
|
||||
// t show [t]iming info (NB: use 'p' flag to avoid GC/scheduler noise)
|
||||
// v show [v]erbose logging
|
||||
//
|
||||
Debug = ""
|
||||
|
||||
// Log files for optional performance tracing.
|
||||
CPUProfile, MemProfile, Trace string
|
||||
)
|
||||
|
||||
// RegisterFlags registers command-line flags used the analysis driver.
|
||||
func RegisterFlags() {
|
||||
// When adding flags here, remember to update
|
||||
// the list of suppressed flags in analysisflags.
|
||||
|
||||
flag.StringVar(&Debug, "debug", Debug, `debug flags, any subset of "lpsv"`)
|
||||
|
||||
flag.StringVar(&CPUProfile, "cpuprofile", "", "write CPU profile to this file")
|
||||
flag.StringVar(&MemProfile, "memprofile", "", "write memory profile to this file")
|
||||
flag.StringVar(&Trace, "trace", "", "write trace log to this file")
|
||||
}
|
||||
|
||||
// Run loads the packages specified by args using go/packages,
|
||||
// then applies the specified analyzers to them.
|
||||
// Analysis flags must already have been set.
|
||||
// It provides most of the logic for the main functions of both the
|
||||
// singlechecker and the multi-analysis commands.
|
||||
// It returns the appropriate exit code.
|
||||
func Run(args []string, analyzers []*analysis.Analyzer) (exitcode int) {
|
||||
if CPUProfile != "" {
|
||||
f, err := os.Create(CPUProfile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := pprof.StartCPUProfile(f); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// NB: profile won't be written in case of error.
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
if Trace != "" {
|
||||
f, err := os.Create(Trace)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := trace.Start(f); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// NB: trace log won't be written in case of error.
|
||||
defer func() {
|
||||
trace.Stop()
|
||||
log.Printf("To view the trace, run:\n$ go tool trace view %s", Trace)
|
||||
}()
|
||||
}
|
||||
|
||||
if MemProfile != "" {
|
||||
f, err := os.Create(MemProfile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// NB: memprofile won't be written in case of error.
|
||||
defer func() {
|
||||
runtime.GC() // get up-to-date statistics
|
||||
if err := pprof.WriteHeapProfile(f); err != nil {
|
||||
log.Fatalf("Writing memory profile: %v", err)
|
||||
}
|
||||
f.Close()
|
||||
}()
|
||||
}
|
||||
|
||||
// Load the packages.
|
||||
if dbg('v') {
|
||||
log.SetPrefix("")
|
||||
log.SetFlags(log.Lmicroseconds) // display timing
|
||||
log.Printf("load %s", args)
|
||||
}
|
||||
|
||||
// Optimization: if the selected analyzers don't produce/consume
|
||||
// facts, we need source only for the initial packages.
|
||||
allSyntax := needFacts(analyzers)
|
||||
initial, err := load(args, allSyntax)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return 1 // load errors
|
||||
}
|
||||
|
||||
// Print the results.
|
||||
roots := analyze(initial, analyzers)
|
||||
|
||||
return printDiagnostics(roots)
|
||||
}
|
||||
|
||||
// load loads the initial packages.
|
||||
func load(patterns []string, allSyntax bool) ([]*packages.Package, error) {
|
||||
mode := packages.LoadSyntax
|
||||
if allSyntax {
|
||||
mode = packages.LoadAllSyntax
|
||||
}
|
||||
conf := packages.Config{
|
||||
Mode: mode,
|
||||
Tests: true,
|
||||
}
|
||||
initial, err := packages.Load(&conf, patterns...)
|
||||
if err == nil {
|
||||
if n := packages.PrintErrors(initial); n > 1 {
|
||||
err = fmt.Errorf("%d errors during loading", n)
|
||||
} else if n == 1 {
|
||||
err = fmt.Errorf("error during loading")
|
||||
}
|
||||
}
|
||||
if len(initial) == 0 {
|
||||
err = fmt.Errorf("%s matched no packages", strings.Join(patterns, " "))
|
||||
}
|
||||
return initial, err
|
||||
}
|
||||
|
||||
// TestAnalyzer applies an analysis to a set of packages (and their
|
||||
// dependencies if necessary) and returns the results.
|
||||
//
|
||||
// Facts about pkg are returned in a map keyed by object; package facts
|
||||
// have a nil key.
|
||||
//
|
||||
// This entry point is used only by analysistest.
|
||||
func TestAnalyzer(a *analysis.Analyzer, pkgs []*packages.Package) []*TestAnalyzerResult {
|
||||
var results []*TestAnalyzerResult
|
||||
for _, act := range analyze(pkgs, []*analysis.Analyzer{a}) {
|
||||
facts := make(map[types.Object][]analysis.Fact)
|
||||
for key, fact := range act.objectFacts {
|
||||
if key.obj.Pkg() == act.pass.Pkg {
|
||||
facts[key.obj] = append(facts[key.obj], fact)
|
||||
}
|
||||
}
|
||||
for key, fact := range act.packageFacts {
|
||||
if key.pkg == act.pass.Pkg {
|
||||
facts[nil] = append(facts[nil], fact)
|
||||
}
|
||||
}
|
||||
|
||||
results = append(results, &TestAnalyzerResult{act.pass, act.diagnostics, facts, act.result, act.err})
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
type TestAnalyzerResult struct {
|
||||
Pass *analysis.Pass
|
||||
Diagnostics []analysis.Diagnostic
|
||||
Facts map[types.Object][]analysis.Fact
|
||||
Result interface{}
|
||||
Err error
|
||||
}
|
||||
|
||||
func analyze(pkgs []*packages.Package, analyzers []*analysis.Analyzer) []*action {
|
||||
// Construct the action graph.
|
||||
if dbg('v') {
|
||||
log.Printf("building graph of analysis passes")
|
||||
}
|
||||
|
||||
// Each graph node (action) is one unit of analysis.
|
||||
// Edges express package-to-package (vertical) dependencies,
|
||||
// and analysis-to-analysis (horizontal) dependencies.
|
||||
type key struct {
|
||||
*analysis.Analyzer
|
||||
*packages.Package
|
||||
}
|
||||
actions := make(map[key]*action)
|
||||
|
||||
var mkAction func(a *analysis.Analyzer, pkg *packages.Package) *action
|
||||
mkAction = func(a *analysis.Analyzer, pkg *packages.Package) *action {
|
||||
k := key{a, pkg}
|
||||
act, ok := actions[k]
|
||||
if !ok {
|
||||
act = &action{a: a, pkg: pkg}
|
||||
|
||||
// Add a dependency on each required analyzers.
|
||||
for _, req := range a.Requires {
|
||||
act.deps = append(act.deps, mkAction(req, pkg))
|
||||
}
|
||||
|
||||
// An analysis that consumes/produces facts
|
||||
// must run on the package's dependencies too.
|
||||
if len(a.FactTypes) > 0 {
|
||||
paths := make([]string, 0, len(pkg.Imports))
|
||||
for path := range pkg.Imports {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
sort.Strings(paths) // for determinism
|
||||
for _, path := range paths {
|
||||
dep := mkAction(a, pkg.Imports[path])
|
||||
act.deps = append(act.deps, dep)
|
||||
}
|
||||
}
|
||||
|
||||
actions[k] = act
|
||||
}
|
||||
return act
|
||||
}
|
||||
|
||||
// Build nodes for initial packages.
|
||||
var roots []*action
|
||||
for _, a := range analyzers {
|
||||
for _, pkg := range pkgs {
|
||||
root := mkAction(a, pkg)
|
||||
root.isroot = true
|
||||
roots = append(roots, root)
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the graph in parallel.
|
||||
execAll(roots)
|
||||
|
||||
return roots
|
||||
}
|
||||
|
||||
// printDiagnostics prints the diagnostics for the root packages in either
|
||||
// plain text or JSON format. JSON format also includes errors for any
|
||||
// dependencies.
|
||||
//
|
||||
// It returns the exitcode: in plain mode, 0 for success, 1 for analysis
|
||||
// errors, and 3 for diagnostics. We avoid 2 since the flag package uses
|
||||
// it. JSON mode always succeeds at printing errors and diagnostics in a
|
||||
// structured form to stdout.
|
||||
func printDiagnostics(roots []*action) (exitcode int) {
|
||||
// Print the output.
|
||||
//
|
||||
// Print diagnostics only for root packages,
|
||||
// but errors for all packages.
|
||||
printed := make(map[*action]bool)
|
||||
var print func(*action)
|
||||
var visitAll func(actions []*action)
|
||||
visitAll = func(actions []*action) {
|
||||
for _, act := range actions {
|
||||
if !printed[act] {
|
||||
printed[act] = true
|
||||
visitAll(act.deps)
|
||||
print(act)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if analysisflags.JSON {
|
||||
// JSON output
|
||||
tree := make(analysisflags.JSONTree)
|
||||
print = func(act *action) {
|
||||
var diags []analysis.Diagnostic
|
||||
if act.isroot {
|
||||
diags = act.diagnostics
|
||||
}
|
||||
tree.Add(act.pkg.Fset, act.pkg.ID, act.a.Name, diags, act.err)
|
||||
}
|
||||
visitAll(roots)
|
||||
tree.Print()
|
||||
} else {
|
||||
// plain text output
|
||||
|
||||
// De-duplicate diagnostics by position (not token.Pos) to
|
||||
// avoid double-reporting in source files that belong to
|
||||
// multiple packages, such as foo and foo.test.
|
||||
type key struct {
|
||||
token.Position
|
||||
*analysis.Analyzer
|
||||
message string
|
||||
}
|
||||
seen := make(map[key]bool)
|
||||
|
||||
print = func(act *action) {
|
||||
if act.err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s: %v\n", act.a.Name, act.err)
|
||||
exitcode = 1 // analysis failed, at least partially
|
||||
return
|
||||
}
|
||||
if act.isroot {
|
||||
for _, diag := range act.diagnostics {
|
||||
// We don't display a.Name/f.Category
|
||||
// as most users don't care.
|
||||
|
||||
posn := act.pkg.Fset.Position(diag.Pos)
|
||||
k := key{posn, act.a, diag.Message}
|
||||
if seen[k] {
|
||||
continue // duplicate
|
||||
}
|
||||
seen[k] = true
|
||||
|
||||
analysisflags.PrintPlain(act.pkg.Fset, diag)
|
||||
}
|
||||
}
|
||||
}
|
||||
visitAll(roots)
|
||||
|
||||
if exitcode == 0 && len(seen) > 0 {
|
||||
exitcode = 3 // successfuly produced diagnostics
|
||||
}
|
||||
}
|
||||
|
||||
// Print timing info.
|
||||
if dbg('t') {
|
||||
if !dbg('p') {
|
||||
log.Println("Warning: times are mostly GC/scheduler noise; use -debug=tp to disable parallelism")
|
||||
}
|
||||
var all []*action
|
||||
var total time.Duration
|
||||
for act := range printed {
|
||||
all = append(all, act)
|
||||
total += act.duration
|
||||
}
|
||||
sort.Slice(all, func(i, j int) bool {
|
||||
return all[i].duration > all[j].duration
|
||||
})
|
||||
|
||||
// Print actions accounting for 90% of the total.
|
||||
var sum time.Duration
|
||||
for _, act := range all {
|
||||
fmt.Fprintf(os.Stderr, "%s\t%s\n", act.duration, act)
|
||||
sum += act.duration
|
||||
if sum >= total*9/10 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return exitcode
|
||||
}
|
||||
|
||||
// needFacts reports whether any analysis required by the specified set
|
||||
// needs facts. If so, we must load the entire program from source.
|
||||
func needFacts(analyzers []*analysis.Analyzer) bool {
|
||||
seen := make(map[*analysis.Analyzer]bool)
|
||||
var q []*analysis.Analyzer // for BFS
|
||||
q = append(q, analyzers...)
|
||||
for len(q) > 0 {
|
||||
a := q[0]
|
||||
q = q[1:]
|
||||
if !seen[a] {
|
||||
seen[a] = true
|
||||
if len(a.FactTypes) > 0 {
|
||||
return true
|
||||
}
|
||||
q = append(q, a.Requires...)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// An action represents one unit of analysis work: the application of
|
||||
// one analysis to one package. Actions form a DAG, both within a
|
||||
// package (as different analyzers are applied, either in sequence or
|
||||
// parallel), and across packages (as dependencies are analyzed).
|
||||
type action struct {
|
||||
once sync.Once
|
||||
a *analysis.Analyzer
|
||||
pkg *packages.Package
|
||||
pass *analysis.Pass
|
||||
isroot bool
|
||||
deps []*action
|
||||
objectFacts map[objectFactKey]analysis.Fact
|
||||
packageFacts map[packageFactKey]analysis.Fact
|
||||
inputs map[*analysis.Analyzer]interface{}
|
||||
result interface{}
|
||||
diagnostics []analysis.Diagnostic
|
||||
err error
|
||||
duration time.Duration
|
||||
}
|
||||
|
||||
type objectFactKey struct {
|
||||
obj types.Object
|
||||
typ reflect.Type
|
||||
}
|
||||
|
||||
type packageFactKey struct {
|
||||
pkg *types.Package
|
||||
typ reflect.Type
|
||||
}
|
||||
|
||||
func (act *action) String() string {
|
||||
return fmt.Sprintf("%s@%s", act.a, act.pkg)
|
||||
}
|
||||
|
||||
func execAll(actions []*action) {
|
||||
sequential := dbg('p')
|
||||
var wg sync.WaitGroup
|
||||
for _, act := range actions {
|
||||
wg.Add(1)
|
||||
work := func(act *action) {
|
||||
act.exec()
|
||||
wg.Done()
|
||||
}
|
||||
if sequential {
|
||||
work(act)
|
||||
} else {
|
||||
go work(act)
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (act *action) exec() { act.once.Do(act.execOnce) }
|
||||
|
||||
func (act *action) execOnce() {
|
||||
// Analyze dependencies.
|
||||
execAll(act.deps)
|
||||
|
||||
// TODO(adonovan): uncomment this during profiling.
|
||||
// It won't build pre-go1.11 but conditional compilation
|
||||
// using build tags isn't warranted.
|
||||
//
|
||||
// ctx, task := trace.NewTask(context.Background(), "exec")
|
||||
// trace.Log(ctx, "pass", act.String())
|
||||
// defer task.End()
|
||||
|
||||
// Record time spent in this node but not its dependencies.
|
||||
// In parallel mode, due to GC/scheduler contention, the
|
||||
// time is 5x higher than in sequential mode, even with a
|
||||
// semaphore limiting the number of threads here.
|
||||
// So use -debug=tp.
|
||||
if dbg('t') {
|
||||
t0 := time.Now()
|
||||
defer func() { act.duration = time.Since(t0) }()
|
||||
}
|
||||
|
||||
// Report an error if any dependency failed.
|
||||
var failed []string
|
||||
for _, dep := range act.deps {
|
||||
if dep.err != nil {
|
||||
failed = append(failed, dep.String())
|
||||
}
|
||||
}
|
||||
if failed != nil {
|
||||
sort.Strings(failed)
|
||||
act.err = fmt.Errorf("failed prerequisites: %s", strings.Join(failed, ", "))
|
||||
return
|
||||
}
|
||||
|
||||
// Plumb the output values of the dependencies
|
||||
// into the inputs of this action. Also facts.
|
||||
inputs := make(map[*analysis.Analyzer]interface{})
|
||||
act.objectFacts = make(map[objectFactKey]analysis.Fact)
|
||||
act.packageFacts = make(map[packageFactKey]analysis.Fact)
|
||||
for _, dep := range act.deps {
|
||||
if dep.pkg == act.pkg {
|
||||
// Same package, different analysis (horizontal edge):
|
||||
// in-memory outputs of prerequisite analyzers
|
||||
// become inputs to this analysis pass.
|
||||
inputs[dep.a] = dep.result
|
||||
|
||||
} else if dep.a == act.a { // (always true)
|
||||
// Same analysis, different package (vertical edge):
|
||||
// serialized facts produced by prerequisite analysis
|
||||
// become available to this analysis pass.
|
||||
inheritFacts(act, dep)
|
||||
}
|
||||
}
|
||||
|
||||
// Run the analysis.
|
||||
pass := &analysis.Pass{
|
||||
Analyzer: act.a,
|
||||
Fset: act.pkg.Fset,
|
||||
Files: act.pkg.Syntax,
|
||||
OtherFiles: act.pkg.OtherFiles,
|
||||
Pkg: act.pkg.Types,
|
||||
TypesInfo: act.pkg.TypesInfo,
|
||||
ResultOf: inputs,
|
||||
Report: func(d analysis.Diagnostic) { act.diagnostics = append(act.diagnostics, d) },
|
||||
ImportObjectFact: act.importObjectFact,
|
||||
ExportObjectFact: act.exportObjectFact,
|
||||
ImportPackageFact: act.importPackageFact,
|
||||
ExportPackageFact: act.exportPackageFact,
|
||||
}
|
||||
act.pass = pass
|
||||
|
||||
var err error
|
||||
if act.pkg.IllTyped && !pass.Analyzer.RunDespiteErrors {
|
||||
err = fmt.Errorf("analysis skipped due to errors in package")
|
||||
} else {
|
||||
act.result, err = pass.Analyzer.Run(pass)
|
||||
if err == nil {
|
||||
if got, want := reflect.TypeOf(act.result), pass.Analyzer.ResultType; got != want {
|
||||
err = fmt.Errorf(
|
||||
"internal error: on package %s, analyzer %s returned a result of type %v, but declared ResultType %v",
|
||||
pass.Pkg.Path(), pass.Analyzer, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
act.err = err
|
||||
|
||||
// disallow calls after Run
|
||||
pass.ExportObjectFact = nil
|
||||
pass.ExportPackageFact = nil
|
||||
}
|
||||
|
||||
// inheritFacts populates act.facts with
|
||||
// those it obtains from its dependency, dep.
|
||||
func inheritFacts(act, dep *action) {
|
||||
serialize := dbg('s')
|
||||
|
||||
for key, fact := range dep.objectFacts {
|
||||
// Filter out facts related to objects
|
||||
// that are irrelevant downstream
|
||||
// (equivalently: not in the compiler export data).
|
||||
if !exportedFrom(key.obj, dep.pkg.Types) {
|
||||
if false {
|
||||
log.Printf("%v: discarding %T fact from %s for %s: %s", act, fact, dep, key.obj, fact)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Optionally serialize/deserialize fact
|
||||
// to verify that it works across address spaces.
|
||||
if serialize {
|
||||
var err error
|
||||
fact, err = codeFact(fact)
|
||||
if err != nil {
|
||||
log.Panicf("internal error: encoding of %T fact failed in %v", fact, act)
|
||||
}
|
||||
}
|
||||
|
||||
if false {
|
||||
log.Printf("%v: inherited %T fact for %s: %s", act, fact, key.obj, fact)
|
||||
}
|
||||
act.objectFacts[key] = fact
|
||||
}
|
||||
|
||||
for key, fact := range dep.packageFacts {
|
||||
// TODO: filter out facts that belong to
|
||||
// packages not mentioned in the export data
|
||||
// to prevent side channels.
|
||||
|
||||
// Optionally serialize/deserialize fact
|
||||
// to verify that it works across address spaces
|
||||
// and is deterministic.
|
||||
if serialize {
|
||||
var err error
|
||||
fact, err = codeFact(fact)
|
||||
if err != nil {
|
||||
log.Panicf("internal error: encoding of %T fact failed in %v", fact, act)
|
||||
}
|
||||
}
|
||||
|
||||
if false {
|
||||
log.Printf("%v: inherited %T fact for %s: %s", act, fact, key.pkg.Path(), fact)
|
||||
}
|
||||
act.packageFacts[key] = fact
|
||||
}
|
||||
}
|
||||
|
||||
// codeFact encodes then decodes a fact,
|
||||
// just to exercise that logic.
|
||||
func codeFact(fact analysis.Fact) (analysis.Fact, error) {
|
||||
// We encode facts one at a time.
|
||||
// A real modular driver would emit all facts
|
||||
// into one encoder to improve gob efficiency.
|
||||
var buf bytes.Buffer
|
||||
if err := gob.NewEncoder(&buf).Encode(fact); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Encode it twice and assert that we get the same bits.
|
||||
// This helps detect nondeterministic Gob encoding (e.g. of maps).
|
||||
var buf2 bytes.Buffer
|
||||
if err := gob.NewEncoder(&buf2).Encode(fact); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), buf2.Bytes()) {
|
||||
return nil, fmt.Errorf("encoding of %T fact is nondeterministic", fact)
|
||||
}
|
||||
|
||||
new := reflect.New(reflect.TypeOf(fact).Elem()).Interface().(analysis.Fact)
|
||||
if err := gob.NewDecoder(&buf).Decode(new); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return new, nil
|
||||
}
|
||||
|
||||
// exportedFrom reports whether obj may be visible to a package that imports pkg.
|
||||
// This includes not just the exported members of pkg, but also unexported
|
||||
// constants, types, fields, and methods, perhaps belonging to oether packages,
|
||||
// that find there way into the API.
|
||||
// This is an overapproximation of the more accurate approach used by
|
||||
// gc export data, which walks the type graph, but it's much simpler.
|
||||
//
|
||||
// TODO(adonovan): do more accurate filtering by walking the type graph.
|
||||
func exportedFrom(obj types.Object, pkg *types.Package) bool {
|
||||
switch obj := obj.(type) {
|
||||
case *types.Func:
|
||||
return obj.Exported() && obj.Pkg() == pkg ||
|
||||
obj.Type().(*types.Signature).Recv() != nil
|
||||
case *types.Var:
|
||||
return obj.Exported() && obj.Pkg() == pkg ||
|
||||
obj.IsField()
|
||||
case *types.TypeName, *types.Const:
|
||||
return true
|
||||
}
|
||||
return false // Nil, Builtin, Label, or PkgName
|
||||
}
|
||||
|
||||
// importObjectFact implements Pass.ImportObjectFact.
|
||||
// Given a non-nil pointer ptr of type *T, where *T satisfies Fact,
|
||||
// importObjectFact copies the fact value to *ptr.
|
||||
func (act *action) importObjectFact(obj types.Object, ptr analysis.Fact) bool {
|
||||
if obj == nil {
|
||||
panic("nil object")
|
||||
}
|
||||
key := objectFactKey{obj, factType(ptr)}
|
||||
if v, ok := act.objectFacts[key]; ok {
|
||||
reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// exportObjectFact implements Pass.ExportObjectFact.
|
||||
func (act *action) exportObjectFact(obj types.Object, fact analysis.Fact) {
|
||||
if act.pass.ExportObjectFact == nil {
|
||||
log.Panicf("%s: Pass.ExportObjectFact(%s, %T) called after Run", act, obj, fact)
|
||||
}
|
||||
|
||||
if obj.Pkg() != act.pkg.Types {
|
||||
log.Panicf("internal error: in analysis %s of package %s: Fact.Set(%s, %T): can't set facts on objects belonging another package",
|
||||
act.a, act.pkg, obj, fact)
|
||||
}
|
||||
|
||||
key := objectFactKey{obj, factType(fact)}
|
||||
act.objectFacts[key] = fact // clobber any existing entry
|
||||
if dbg('f') {
|
||||
objstr := types.ObjectString(obj, (*types.Package).Name)
|
||||
fmt.Fprintf(os.Stderr, "%s: object %s has fact %s\n",
|
||||
act.pkg.Fset.Position(obj.Pos()), objstr, fact)
|
||||
}
|
||||
}
|
||||
|
||||
// importPackageFact implements Pass.ImportPackageFact.
|
||||
// Given a non-nil pointer ptr of type *T, where *T satisfies Fact,
|
||||
// fact copies the fact value to *ptr.
|
||||
func (act *action) importPackageFact(pkg *types.Package, ptr analysis.Fact) bool {
|
||||
if pkg == nil {
|
||||
panic("nil package")
|
||||
}
|
||||
key := packageFactKey{pkg, factType(ptr)}
|
||||
if v, ok := act.packageFacts[key]; ok {
|
||||
reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// exportPackageFact implements Pass.ExportPackageFact.
|
||||
func (act *action) exportPackageFact(fact analysis.Fact) {
|
||||
if act.pass.ExportPackageFact == nil {
|
||||
log.Panicf("%s: Pass.ExportPackageFact(%T) called after Run", act, fact)
|
||||
}
|
||||
|
||||
key := packageFactKey{act.pass.Pkg, factType(fact)}
|
||||
act.packageFacts[key] = fact // clobber any existing entry
|
||||
if dbg('f') {
|
||||
fmt.Fprintf(os.Stderr, "%s: package %s has fact %s\n",
|
||||
act.pkg.Fset.Position(act.pass.Files[0].Pos()), act.pass.Pkg.Path(), fact)
|
||||
}
|
||||
}
|
||||
|
||||
func factType(fact analysis.Fact) reflect.Type {
|
||||
t := reflect.TypeOf(fact)
|
||||
if t.Kind() != reflect.Ptr {
|
||||
log.Fatalf("invalid Fact type: got %T, want pointer", t)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func dbg(b byte) bool { return strings.IndexByte(Debug, b) >= 0 }
|
||||
299
vendor/golang.org/x/tools/go/analysis/internal/facts/facts.go
generated
vendored
Normal file
299
vendor/golang.org/x/tools/go/analysis/internal/facts/facts.go
generated
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// Package facts defines a serializable set of analysis.Fact.
|
||||
//
|
||||
// It provides a partial implementation of the Fact-related parts of the
|
||||
// analysis.Pass interface for use in analysis drivers such as "go vet"
|
||||
// and other build systems.
|
||||
//
|
||||
// The serial format is unspecified and may change, so the same version
|
||||
// of this package must be used for reading and writing serialized facts.
|
||||
//
|
||||
// The handling of facts in the analysis system parallels the handling
|
||||
// of type information in the compiler: during compilation of package P,
|
||||
// the compiler emits an export data file that describes the type of
|
||||
// every object (named thing) defined in package P, plus every object
|
||||
// indirectly reachable from one of those objects. Thus the downstream
|
||||
// compiler of package Q need only load one export data file per direct
|
||||
// import of Q, and it will learn everything about the API of package P
|
||||
// and everything it needs to know about the API of P's dependencies.
|
||||
//
|
||||
// Similarly, analysis of package P emits a fact set containing facts
|
||||
// about all objects exported from P, plus additional facts about only
|
||||
// those objects of P's dependencies that are reachable from the API of
|
||||
// package P; the downstream analysis of Q need only load one fact set
|
||||
// per direct import of Q.
|
||||
//
|
||||
// The notion of "exportedness" that matters here is that of the
|
||||
// compiler. According to the language spec, a method pkg.T.f is
|
||||
// unexported simply because its name starts with lowercase. But the
|
||||
// compiler must nonethless export f so that downstream compilations can
|
||||
// accurately ascertain whether pkg.T implements an interface pkg.I
|
||||
// defined as interface{f()}. Exported thus means "described in export
|
||||
// data".
|
||||
//
|
||||
package facts
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/types/objectpath"
|
||||
)
|
||||
|
||||
const debug = false
|
||||
|
||||
// A Set is a set of analysis.Facts.
|
||||
//
|
||||
// Decode creates a Set of facts by reading from the imports of a given
|
||||
// package, and Encode writes out the set. Between these operation,
|
||||
// the Import and Export methods will query and update the set.
|
||||
//
|
||||
// All of Set's methods except String are safe to call concurrently.
|
||||
type Set struct {
|
||||
pkg *types.Package
|
||||
mu sync.Mutex
|
||||
m map[key]analysis.Fact
|
||||
}
|
||||
|
||||
type key struct {
|
||||
pkg *types.Package
|
||||
obj types.Object // (object facts only)
|
||||
t reflect.Type
|
||||
}
|
||||
|
||||
// ImportObjectFact implements analysis.Pass.ImportObjectFact.
|
||||
func (s *Set) ImportObjectFact(obj types.Object, ptr analysis.Fact) bool {
|
||||
if obj == nil {
|
||||
panic("nil object")
|
||||
}
|
||||
key := key{pkg: obj.Pkg(), obj: obj, t: reflect.TypeOf(ptr)}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if v, ok := s.m[key]; ok {
|
||||
reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ExportObjectFact implements analysis.Pass.ExportObjectFact.
|
||||
func (s *Set) ExportObjectFact(obj types.Object, fact analysis.Fact) {
|
||||
if obj.Pkg() != s.pkg {
|
||||
log.Panicf("in package %s: ExportObjectFact(%s, %T): can't set fact on object belonging another package",
|
||||
s.pkg, obj, fact)
|
||||
}
|
||||
key := key{pkg: obj.Pkg(), obj: obj, t: reflect.TypeOf(fact)}
|
||||
s.mu.Lock()
|
||||
s.m[key] = fact // clobber any existing entry
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
// ImportPackageFact implements analysis.Pass.ImportPackageFact.
|
||||
func (s *Set) ImportPackageFact(pkg *types.Package, ptr analysis.Fact) bool {
|
||||
if pkg == nil {
|
||||
panic("nil package")
|
||||
}
|
||||
key := key{pkg: pkg, t: reflect.TypeOf(ptr)}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if v, ok := s.m[key]; ok {
|
||||
reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem())
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ExportPackageFact implements analysis.Pass.ExportPackageFact.
|
||||
func (s *Set) ExportPackageFact(fact analysis.Fact) {
|
||||
key := key{pkg: s.pkg, t: reflect.TypeOf(fact)}
|
||||
s.mu.Lock()
|
||||
s.m[key] = fact // clobber any existing entry
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
// gobFact is the Gob declaration of a serialized fact.
|
||||
type gobFact struct {
|
||||
PkgPath string // path of package
|
||||
Object objectpath.Path // optional path of object relative to package itself
|
||||
Fact analysis.Fact // type and value of user-defined Fact
|
||||
}
|
||||
|
||||
// Decode decodes all the facts relevant to the analysis of package pkg.
|
||||
// The read function reads serialized fact data from an external source
|
||||
// for one of of pkg's direct imports. The empty file is a valid
|
||||
// encoding of an empty fact set.
|
||||
//
|
||||
// It is the caller's responsibility to call gob.Register on all
|
||||
// necessary fact types.
|
||||
func Decode(pkg *types.Package, read func(packagePath string) ([]byte, error)) (*Set, error) {
|
||||
// Compute the import map for this package.
|
||||
// See the package doc comment.
|
||||
packages := importMap(pkg.Imports())
|
||||
|
||||
// Read facts from imported packages.
|
||||
// Facts may describe indirectly imported packages, or their objects.
|
||||
m := make(map[key]analysis.Fact) // one big bucket
|
||||
for _, imp := range pkg.Imports() {
|
||||
logf := func(format string, args ...interface{}) {
|
||||
if debug {
|
||||
prefix := fmt.Sprintf("in %s, importing %s: ",
|
||||
pkg.Path(), imp.Path())
|
||||
log.Print(prefix, fmt.Sprintf(format, args...))
|
||||
}
|
||||
}
|
||||
|
||||
// Read the gob-encoded facts.
|
||||
data, err := read(imp.Path())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("in %s, can't import facts for package %q: %v",
|
||||
pkg.Path(), imp.Path(), err)
|
||||
}
|
||||
if len(data) == 0 {
|
||||
continue // no facts
|
||||
}
|
||||
var gobFacts []gobFact
|
||||
if err := gob.NewDecoder(bytes.NewReader(data)).Decode(&gobFacts); err != nil {
|
||||
return nil, fmt.Errorf("decoding facts for %q: %v", imp.Path(), err)
|
||||
}
|
||||
if debug {
|
||||
logf("decoded %d facts: %v", len(gobFacts), gobFacts)
|
||||
}
|
||||
|
||||
// Parse each one into a key and a Fact.
|
||||
for _, f := range gobFacts {
|
||||
factPkg := packages[f.PkgPath]
|
||||
if factPkg == nil {
|
||||
// Fact relates to a dependency that was
|
||||
// unused in this translation unit. Skip.
|
||||
logf("no package %q; discarding %v", f.PkgPath, f.Fact)
|
||||
continue
|
||||
}
|
||||
key := key{pkg: factPkg, t: reflect.TypeOf(f.Fact)}
|
||||
if f.Object != "" {
|
||||
// object fact
|
||||
obj, err := objectpath.Object(factPkg, f.Object)
|
||||
if err != nil {
|
||||
// (most likely due to unexported object)
|
||||
// TODO(adonovan): audit for other possibilities.
|
||||
logf("no object for path: %v; discarding %s", err, f.Fact)
|
||||
continue
|
||||
}
|
||||
key.obj = obj
|
||||
logf("read %T fact %s for %v", f.Fact, f.Fact, key.obj)
|
||||
} else {
|
||||
// package fact
|
||||
logf("read %T fact %s for %v", f.Fact, f.Fact, factPkg)
|
||||
}
|
||||
m[key] = f.Fact
|
||||
}
|
||||
}
|
||||
|
||||
return &Set{pkg: pkg, m: m}, nil
|
||||
}
|
||||
|
||||
// Encode encodes a set of facts to a memory buffer.
|
||||
//
|
||||
// It may fail if one of the Facts could not be gob-encoded, but this is
|
||||
// a sign of a bug in an Analyzer.
|
||||
func (s *Set) Encode() []byte {
|
||||
|
||||
// TODO(adonovan): opt: use a more efficient encoding
|
||||
// that avoids repeating PkgPath for each fact.
|
||||
|
||||
// Gather all facts, including those from imported packages.
|
||||
var gobFacts []gobFact
|
||||
|
||||
s.mu.Lock()
|
||||
for k, fact := range s.m {
|
||||
if debug {
|
||||
log.Printf("%v => %s\n", k, fact)
|
||||
}
|
||||
var object objectpath.Path
|
||||
if k.obj != nil {
|
||||
path, err := objectpath.For(k.obj)
|
||||
if err != nil {
|
||||
if debug {
|
||||
log.Printf("discarding fact %s about %s\n", fact, k.obj)
|
||||
}
|
||||
continue // object not accessible from package API; discard fact
|
||||
}
|
||||
object = path
|
||||
}
|
||||
gobFacts = append(gobFacts, gobFact{
|
||||
PkgPath: k.pkg.Path(),
|
||||
Object: object,
|
||||
Fact: fact,
|
||||
})
|
||||
}
|
||||
s.mu.Unlock()
|
||||
|
||||
// Sort facts by (package, object, type) for determinism.
|
||||
sort.Slice(gobFacts, func(i, j int) bool {
|
||||
x, y := gobFacts[i], gobFacts[j]
|
||||
if x.PkgPath != y.PkgPath {
|
||||
return x.PkgPath < y.PkgPath
|
||||
}
|
||||
if x.Object != y.Object {
|
||||
return x.Object < y.Object
|
||||
}
|
||||
tx := reflect.TypeOf(x.Fact)
|
||||
ty := reflect.TypeOf(y.Fact)
|
||||
if tx != ty {
|
||||
return tx.String() < ty.String()
|
||||
}
|
||||
return false // equal
|
||||
})
|
||||
|
||||
var buf bytes.Buffer
|
||||
if len(gobFacts) > 0 {
|
||||
if err := gob.NewEncoder(&buf).Encode(gobFacts); err != nil {
|
||||
// Fact encoding should never fail. Identify the culprit.
|
||||
for _, gf := range gobFacts {
|
||||
if err := gob.NewEncoder(ioutil.Discard).Encode(gf); err != nil {
|
||||
fact := gf.Fact
|
||||
pkgpath := reflect.TypeOf(fact).Elem().PkgPath()
|
||||
log.Panicf("internal error: gob encoding of analysis fact %s failed: %v; please report a bug against fact %T in package %q",
|
||||
fact, err, fact, pkgpath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if debug {
|
||||
log.Printf("package %q: encode %d facts, %d bytes\n",
|
||||
s.pkg.Path(), len(gobFacts), buf.Len())
|
||||
}
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// String is provided only for debugging, and must not be called
|
||||
// concurrent with any Import/Export method.
|
||||
func (s *Set) String() string {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("{")
|
||||
for k, f := range s.m {
|
||||
if buf.Len() > 1 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
if k.obj != nil {
|
||||
buf.WriteString(k.obj.String())
|
||||
} else {
|
||||
buf.WriteString(k.pkg.Path())
|
||||
}
|
||||
fmt.Fprintf(&buf, ": %v", f)
|
||||
}
|
||||
buf.WriteString("}")
|
||||
return buf.String()
|
||||
}
|
||||
174
vendor/golang.org/x/tools/go/analysis/internal/facts/facts_test.go
generated
vendored
Normal file
174
vendor/golang.org/x/tools/go/analysis/internal/facts/facts_test.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
package facts_test
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
"golang.org/x/tools/go/analysis/internal/facts"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
type myFact struct {
|
||||
S string
|
||||
}
|
||||
|
||||
func (f *myFact) String() string { return fmt.Sprintf("myFact(%s)", f.S) }
|
||||
func (f *myFact) AFact() {}
|
||||
|
||||
func TestEncodeDecode(t *testing.T) {
|
||||
gob.Register(new(myFact))
|
||||
|
||||
// c -> b -> a, a2
|
||||
// c does not directly depend on a, but it indirectly uses a.T.
|
||||
//
|
||||
// Package a2 is never loaded directly so it is incomplete.
|
||||
//
|
||||
// We use only types in this example because we rely on
|
||||
// types.Eval to resolve the lookup expressions, and it only
|
||||
// works for types. This is a definite gap in the typechecker API.
|
||||
files := map[string]string{
|
||||
"a/a.go": `package a; type A int; type T int`,
|
||||
"a2/a.go": `package a2; type A2 int; type Unneeded int`,
|
||||
"b/b.go": `package b; import ("a"; "a2"); type B chan a2.A2; type F func() a.T`,
|
||||
"c/c.go": `package c; import "b"; type C []b.B`,
|
||||
}
|
||||
dir, cleanup, err := analysistest.WriteFiles(files)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
// factmap represents the passing of encoded facts from one
|
||||
// package to another. In practice one would use the file system.
|
||||
factmap := make(map[string][]byte)
|
||||
read := func(path string) ([]byte, error) { return factmap[path], nil }
|
||||
|
||||
// In the following table, we analyze packages (a, b, c) in order,
|
||||
// look up various objects accessible within each package,
|
||||
// and see if they have a fact. The "analysis" exports a fact
|
||||
// for every object at package level.
|
||||
//
|
||||
// Note: Loop iterations are not independent test cases;
|
||||
// order matters, as we populate factmap.
|
||||
type lookups []struct {
|
||||
objexpr string
|
||||
want string
|
||||
}
|
||||
for _, test := range []struct {
|
||||
path string
|
||||
lookups lookups
|
||||
}{
|
||||
{"a", lookups{
|
||||
{"A", "myFact(a.A)"},
|
||||
}},
|
||||
{"b", lookups{
|
||||
{"a.A", "myFact(a.A)"},
|
||||
{"a.T", "myFact(a.T)"},
|
||||
{"B", "myFact(b.B)"},
|
||||
{"F", "myFact(b.F)"},
|
||||
{"F(nil)()", "myFact(a.T)"}, // (result type of b.F)
|
||||
}},
|
||||
{"c", lookups{
|
||||
{"b.B", "myFact(b.B)"},
|
||||
{"b.F", "myFact(b.F)"},
|
||||
//{"b.F(nil)()", "myFact(a.T)"}, // no fact; TODO(adonovan): investigate
|
||||
{"C", "myFact(c.C)"},
|
||||
{"C{}[0]", "myFact(b.B)"},
|
||||
{"<-(C{}[0])", "no fact"}, // object but no fact (we never "analyze" a2)
|
||||
}},
|
||||
} {
|
||||
// load package
|
||||
pkg, err := load(dir, test.path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// decode
|
||||
facts, err := facts.Decode(pkg, read)
|
||||
if err != nil {
|
||||
t.Fatalf("Decode failed: %v", err)
|
||||
}
|
||||
if true {
|
||||
t.Logf("decode %s facts = %v", pkg.Path(), facts) // show all facts
|
||||
}
|
||||
|
||||
// export
|
||||
// (one fact for each package-level object)
|
||||
scope := pkg.Scope()
|
||||
for _, name := range scope.Names() {
|
||||
obj := scope.Lookup(name)
|
||||
fact := &myFact{obj.Pkg().Name() + "." + obj.Name()}
|
||||
facts.ExportObjectFact(obj, fact)
|
||||
}
|
||||
|
||||
// import
|
||||
// (after export, because an analyzer may import its own facts)
|
||||
for _, lookup := range test.lookups {
|
||||
fact := new(myFact)
|
||||
var got string
|
||||
if obj := find(pkg, lookup.objexpr); obj == nil {
|
||||
got = "no object"
|
||||
} else if facts.ImportObjectFact(obj, fact) {
|
||||
got = fact.String()
|
||||
} else {
|
||||
got = "no fact"
|
||||
}
|
||||
if got != lookup.want {
|
||||
t.Errorf("in %s, ImportObjectFact(%s, %T) = %s, want %s",
|
||||
pkg.Path(), lookup.objexpr, fact, got, lookup.want)
|
||||
}
|
||||
}
|
||||
|
||||
// encode
|
||||
factmap[pkg.Path()] = facts.Encode()
|
||||
}
|
||||
}
|
||||
|
||||
func find(p *types.Package, expr string) types.Object {
|
||||
// types.Eval only allows us to compute a TypeName object for an expression.
|
||||
// TODO(adonovan): support other expressions that denote an object:
|
||||
// - an identifier (or qualified ident) for a func, const, or var
|
||||
// - new(T).f for a field or method
|
||||
// I've added CheckExpr in https://go-review.googlesource.com/c/go/+/144677.
|
||||
// If that becomes available, use it.
|
||||
|
||||
// Choose an arbitrary position within the (single-file) package
|
||||
// so that we are within the scope of its import declarations.
|
||||
somepos := p.Scope().Lookup(p.Scope().Names()[0]).Pos()
|
||||
tv, err := types.Eval(token.NewFileSet(), p, somepos, expr)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if n, ok := tv.Type.(*types.Named); ok {
|
||||
return n.Obj()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func load(dir string, path string) (*types.Package, error) {
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.LoadSyntax,
|
||||
Dir: dir,
|
||||
Env: append(os.Environ(), "GOPATH="+dir, "GO111MODULE=off", "GOPROXY=off"),
|
||||
}
|
||||
pkgs, err := packages.Load(cfg, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if packages.PrintErrors(pkgs) > 0 {
|
||||
return nil, fmt.Errorf("packages had errors")
|
||||
}
|
||||
if len(pkgs) == 0 {
|
||||
return nil, fmt.Errorf("no package matched %s", path)
|
||||
}
|
||||
return pkgs[0].Types, nil
|
||||
}
|
||||
88
vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go
generated
vendored
Normal file
88
vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
package facts
|
||||
|
||||
import "go/types"
|
||||
|
||||
// importMap computes the import map for a package by traversing the
|
||||
// entire exported API each of its imports.
|
||||
//
|
||||
// This is a workaround for the fact that we cannot access the map used
|
||||
// internally by the types.Importer returned by go/importer. The entries
|
||||
// in this map are the packages and objects that may be relevant to the
|
||||
// current analysis unit.
|
||||
//
|
||||
// Packages in the map that are only indirectly imported may be
|
||||
// incomplete (!pkg.Complete()).
|
||||
//
|
||||
func importMap(imports []*types.Package) map[string]*types.Package {
|
||||
objects := make(map[types.Object]bool)
|
||||
packages := make(map[string]*types.Package)
|
||||
|
||||
var addObj func(obj types.Object) bool
|
||||
var addType func(T types.Type)
|
||||
|
||||
addObj = func(obj types.Object) bool {
|
||||
if !objects[obj] {
|
||||
objects[obj] = true
|
||||
addType(obj.Type())
|
||||
if pkg := obj.Pkg(); pkg != nil {
|
||||
packages[pkg.Path()] = pkg
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
addType = func(T types.Type) {
|
||||
switch T := T.(type) {
|
||||
case *types.Basic:
|
||||
// nop
|
||||
case *types.Named:
|
||||
if addObj(T.Obj()) {
|
||||
for i := 0; i < T.NumMethods(); i++ {
|
||||
addObj(T.Method(i))
|
||||
}
|
||||
}
|
||||
case *types.Pointer:
|
||||
addType(T.Elem())
|
||||
case *types.Slice:
|
||||
addType(T.Elem())
|
||||
case *types.Array:
|
||||
addType(T.Elem())
|
||||
case *types.Chan:
|
||||
addType(T.Elem())
|
||||
case *types.Map:
|
||||
addType(T.Key())
|
||||
addType(T.Elem())
|
||||
case *types.Signature:
|
||||
addType(T.Params())
|
||||
addType(T.Results())
|
||||
case *types.Struct:
|
||||
for i := 0; i < T.NumFields(); i++ {
|
||||
addObj(T.Field(i))
|
||||
}
|
||||
case *types.Tuple:
|
||||
for i := 0; i < T.Len(); i++ {
|
||||
addObj(T.At(i))
|
||||
}
|
||||
case *types.Interface:
|
||||
for i := 0; i < T.NumMethods(); i++ {
|
||||
addObj(T.Method(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, imp := range imports {
|
||||
packages[imp.Path()] = imp
|
||||
|
||||
scope := imp.Scope()
|
||||
for _, name := range scope.Names() {
|
||||
addObj(scope.Lookup(name))
|
||||
}
|
||||
}
|
||||
|
||||
return packages
|
||||
}
|
||||
60
vendor/golang.org/x/tools/go/analysis/multichecker/multichecker.go
generated
vendored
Normal file
60
vendor/golang.org/x/tools/go/analysis/multichecker/multichecker.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// Package multichecker defines the main function for an analysis driver
|
||||
// with several analyzers. This package makes it easy for anyone to build
|
||||
// an analysis tool containing just the analyzers they need.
|
||||
package multichecker
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/internal/analysisflags"
|
||||
"golang.org/x/tools/go/analysis/internal/checker"
|
||||
"golang.org/x/tools/go/analysis/unitchecker"
|
||||
)
|
||||
|
||||
func Main(analyzers ...*analysis.Analyzer) {
|
||||
progname := filepath.Base(os.Args[0])
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix(progname + ": ") // e.g. "vet: "
|
||||
|
||||
if err := analysis.Validate(analyzers); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
checker.RegisterFlags()
|
||||
|
||||
analyzers = analysisflags.Parse(analyzers, true)
|
||||
|
||||
args := flag.Args()
|
||||
if len(args) == 0 {
|
||||
fmt.Fprintf(os.Stderr, `%[1]s is a tool for static analysis of Go programs.
|
||||
|
||||
Usage: %[1]s [-flag] [package]
|
||||
|
||||
Run '%[1]s help' for more detail,
|
||||
or '%[1]s help name' for details and flags of a specific analyzer.
|
||||
`, progname)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if args[0] == "help" {
|
||||
analysisflags.Help(progname, analyzers, args[1:])
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if len(args) == 1 && strings.HasSuffix(args[0], ".cfg") {
|
||||
unitchecker.Run(args[0], analyzers)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
os.Exit(checker.Run(args, analyzers))
|
||||
}
|
||||
82
vendor/golang.org/x/tools/go/analysis/multichecker/multichecker_test.go
generated
vendored
Normal file
82
vendor/golang.org/x/tools/go/analysis/multichecker/multichecker_test.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// +build go1.12
|
||||
|
||||
package multichecker_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/multichecker"
|
||||
"golang.org/x/tools/go/analysis/passes/findcall"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fail := &analysis.Analyzer{
|
||||
Name: "fail",
|
||||
Doc: "always fail on a package 'sort'",
|
||||
Run: func(pass *analysis.Pass) (interface{}, error) {
|
||||
if pass.Pkg.Path() == "sort" {
|
||||
return nil, fmt.Errorf("failed")
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
multichecker.Main(findcall.Analyzer, fail)
|
||||
}
|
||||
|
||||
// TestExitCode ensures that analysis failures are reported correctly.
|
||||
// This test fork/execs the main function above.
|
||||
func TestExitCode(t *testing.T) {
|
||||
if runtime.GOOS != "linux" {
|
||||
t.Skipf("skipping fork/exec test on this platform")
|
||||
}
|
||||
|
||||
if os.Getenv("MULTICHECKER_CHILD") == "1" {
|
||||
// child process
|
||||
|
||||
// replace [progname -test.run=TestExitCode -- ...]
|
||||
// by [progname ...]
|
||||
os.Args = os.Args[2:]
|
||||
os.Args[0] = "vet"
|
||||
main()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
for _, test := range []struct {
|
||||
args []string
|
||||
want int
|
||||
}{
|
||||
{[]string{"nosuchdir/..."}, 1}, // matched no packages
|
||||
{[]string{"nosuchpkg"}, 1}, // matched no packages
|
||||
{[]string{"-unknownflag"}, 2}, // flag error
|
||||
{[]string{"-findcall.name=panic", "io"}, 3}, // finds diagnostics
|
||||
{[]string{"-findcall=0", "io"}, 0}, // no checkers
|
||||
{[]string{"-findcall.name=nosuchfunc", "io"}, 0}, // no diagnostics
|
||||
{[]string{"-findcall.name=panic", "sort", "io"}, 1}, // 'fail' failed on 'sort'
|
||||
|
||||
// -json: exits zero even in face of diagnostics or package errors.
|
||||
{[]string{"-findcall.name=panic", "-json", "io"}, 0},
|
||||
{[]string{"-findcall.name=panic", "-json", "io"}, 0},
|
||||
{[]string{"-findcall.name=panic", "-json", "sort", "io"}, 0},
|
||||
} {
|
||||
args := []string{"-test.run=TestExitCode", "--"}
|
||||
args = append(args, test.args...)
|
||||
cmd := exec.Command(os.Args[0], args...)
|
||||
cmd.Env = append(os.Environ(), "MULTICHECKER_CHILD=1")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if len(out) > 0 {
|
||||
t.Logf("%s: out=<<%s>>", test.args, out)
|
||||
}
|
||||
var exitcode int
|
||||
if err, ok := err.(*exec.ExitError); ok {
|
||||
exitcode = err.ExitCode() // requires go1.12
|
||||
}
|
||||
if exitcode != test.want {
|
||||
t.Errorf("%s: exited %d, want %d", test.args, exitcode, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
8
vendor/golang.org/x/tools/go/analysis/passes/README
generated
vendored
Normal file
8
vendor/golang.org/x/tools/go/analysis/passes/README
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
This directory does not contain a Go package,
|
||||
but acts as a container for various analyses
|
||||
that implement the golang.org/x/tools/go/analysis
|
||||
API and may be imported into an analysis tool.
|
||||
|
||||
By convention, each package foo provides the analysis,
|
||||
and each command foo/cmd/foo provides a standalone driver.
|
||||
760
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
generated
vendored
Normal file
760
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
generated
vendored
Normal file
@@ -0,0 +1,760 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// Package asmdecl defines an Analyzer that reports mismatches between
|
||||
// assembly files and Go declarations.
|
||||
package asmdecl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"log"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
|
||||
)
|
||||
|
||||
var Analyzer = &analysis.Analyzer{
|
||||
Name: "asmdecl",
|
||||
Doc: "report mismatches between assembly files and Go declarations",
|
||||
Run: run,
|
||||
}
|
||||
|
||||
// 'kind' is a kind of assembly variable.
|
||||
// The kinds 1, 2, 4, 8 stand for values of that size.
|
||||
type asmKind int
|
||||
|
||||
// These special kinds are not valid sizes.
|
||||
const (
|
||||
asmString asmKind = 100 + iota
|
||||
asmSlice
|
||||
asmArray
|
||||
asmInterface
|
||||
asmEmptyInterface
|
||||
asmStruct
|
||||
asmComplex
|
||||
)
|
||||
|
||||
// An asmArch describes assembly parameters for an architecture
|
||||
type asmArch struct {
|
||||
name string
|
||||
bigEndian bool
|
||||
stack string
|
||||
lr bool
|
||||
// calculated during initialization
|
||||
sizes types.Sizes
|
||||
intSize int
|
||||
ptrSize int
|
||||
maxAlign int
|
||||
}
|
||||
|
||||
// An asmFunc describes the expected variables for a function on a given architecture.
|
||||
type asmFunc struct {
|
||||
arch *asmArch
|
||||
size int // size of all arguments
|
||||
vars map[string]*asmVar
|
||||
varByOffset map[int]*asmVar
|
||||
}
|
||||
|
||||
// An asmVar describes a single assembly variable.
|
||||
type asmVar struct {
|
||||
name string
|
||||
kind asmKind
|
||||
typ string
|
||||
off int
|
||||
size int
|
||||
inner []*asmVar
|
||||
}
|
||||
|
||||
var (
|
||||
asmArch386 = asmArch{name: "386", bigEndian: false, stack: "SP", lr: false}
|
||||
asmArchArm = asmArch{name: "arm", bigEndian: false, stack: "R13", lr: true}
|
||||
asmArchArm64 = asmArch{name: "arm64", bigEndian: false, stack: "RSP", lr: true}
|
||||
asmArchAmd64 = asmArch{name: "amd64", bigEndian: false, stack: "SP", lr: false}
|
||||
asmArchAmd64p32 = asmArch{name: "amd64p32", bigEndian: false, stack: "SP", lr: false}
|
||||
asmArchMips = asmArch{name: "mips", bigEndian: true, stack: "R29", lr: true}
|
||||
asmArchMipsLE = asmArch{name: "mipsle", bigEndian: false, stack: "R29", lr: true}
|
||||
asmArchMips64 = asmArch{name: "mips64", bigEndian: true, stack: "R29", lr: true}
|
||||
asmArchMips64LE = asmArch{name: "mips64le", bigEndian: false, stack: "R29", lr: true}
|
||||
asmArchPpc64 = asmArch{name: "ppc64", bigEndian: true, stack: "R1", lr: true}
|
||||
asmArchPpc64LE = asmArch{name: "ppc64le", bigEndian: false, stack: "R1", lr: true}
|
||||
asmArchS390X = asmArch{name: "s390x", bigEndian: true, stack: "R15", lr: true}
|
||||
asmArchWasm = asmArch{name: "wasm", bigEndian: false, stack: "SP", lr: false}
|
||||
|
||||
arches = []*asmArch{
|
||||
&asmArch386,
|
||||
&asmArchArm,
|
||||
&asmArchArm64,
|
||||
&asmArchAmd64,
|
||||
&asmArchAmd64p32,
|
||||
&asmArchMips,
|
||||
&asmArchMipsLE,
|
||||
&asmArchMips64,
|
||||
&asmArchMips64LE,
|
||||
&asmArchPpc64,
|
||||
&asmArchPpc64LE,
|
||||
&asmArchS390X,
|
||||
&asmArchWasm,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
for _, arch := range arches {
|
||||
arch.sizes = types.SizesFor("gc", arch.name)
|
||||
if arch.sizes == nil {
|
||||
// TODO(adonovan): fix: now that asmdecl is not in the standard
|
||||
// library we cannot assume types.SizesFor is consistent with arches.
|
||||
// For now, assume 64-bit norms and print a warning.
|
||||
// But this warning should really be deferred until we attempt to use
|
||||
// arch, which is very unlikely.
|
||||
arch.sizes = types.SizesFor("gc", "amd64")
|
||||
log.Printf("unknown architecture %s", arch.name)
|
||||
}
|
||||
arch.intSize = int(arch.sizes.Sizeof(types.Typ[types.Int]))
|
||||
arch.ptrSize = int(arch.sizes.Sizeof(types.Typ[types.UnsafePointer]))
|
||||
arch.maxAlign = int(arch.sizes.Alignof(types.Typ[types.Int64]))
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
re = regexp.MustCompile
|
||||
asmPlusBuild = re(`//\s+\+build\s+([^\n]+)`)
|
||||
asmTEXT = re(`\bTEXT\b(.*)·([^\(]+)\(SB\)(?:\s*,\s*([0-9A-Z|+()]+))?(?:\s*,\s*\$(-?[0-9]+)(?:-([0-9]+))?)?`)
|
||||
asmDATA = re(`\b(DATA|GLOBL)\b`)
|
||||
asmNamedFP = re(`([a-zA-Z0-9_\xFF-\x{10FFFF}]+)(?:\+([0-9]+))\(FP\)`)
|
||||
asmUnnamedFP = re(`[^+\-0-9](([0-9]+)\(FP\))`)
|
||||
asmSP = re(`[^+\-0-9](([0-9]+)\(([A-Z0-9]+)\))`)
|
||||
asmOpcode = re(`^\s*(?:[A-Z0-9a-z_]+:)?\s*([A-Z]+)\s*([^,]*)(?:,\s*(.*))?`)
|
||||
ppc64Suff = re(`([BHWD])(ZU|Z|U|BR)?$`)
|
||||
)
|
||||
|
||||
func run(pass *analysis.Pass) (interface{}, error) {
|
||||
// No work if no assembly files.
|
||||
var sfiles []string
|
||||
for _, fname := range pass.OtherFiles {
|
||||
if strings.HasSuffix(fname, ".s") {
|
||||
sfiles = append(sfiles, fname)
|
||||
}
|
||||
}
|
||||
if sfiles == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Gather declarations. knownFunc[name][arch] is func description.
|
||||
knownFunc := make(map[string]map[string]*asmFunc)
|
||||
|
||||
for _, f := range pass.Files {
|
||||
for _, decl := range f.Decls {
|
||||
if decl, ok := decl.(*ast.FuncDecl); ok && decl.Body == nil {
|
||||
knownFunc[decl.Name.Name] = asmParseDecl(pass, decl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Files:
|
||||
for _, fname := range sfiles {
|
||||
content, tf, err := analysisutil.ReadFile(pass.Fset, fname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Determine architecture from file name if possible.
|
||||
var arch string
|
||||
var archDef *asmArch
|
||||
for _, a := range arches {
|
||||
if strings.HasSuffix(fname, "_"+a.name+".s") {
|
||||
arch = a.name
|
||||
archDef = a
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
lines := strings.SplitAfter(string(content), "\n")
|
||||
var (
|
||||
fn *asmFunc
|
||||
fnName string
|
||||
localSize, argSize int
|
||||
wroteSP bool
|
||||
haveRetArg bool
|
||||
retLine []int
|
||||
)
|
||||
|
||||
flushRet := func() {
|
||||
if fn != nil && fn.vars["ret"] != nil && !haveRetArg && len(retLine) > 0 {
|
||||
v := fn.vars["ret"]
|
||||
for _, line := range retLine {
|
||||
pass.Reportf(analysisutil.LineStart(tf, line), "[%s] %s: RET without writing to %d-byte ret+%d(FP)", arch, fnName, v.size, v.off)
|
||||
}
|
||||
}
|
||||
retLine = nil
|
||||
}
|
||||
for lineno, line := range lines {
|
||||
lineno++
|
||||
|
||||
badf := func(format string, args ...interface{}) {
|
||||
pass.Reportf(analysisutil.LineStart(tf, lineno), "[%s] %s: %s", arch, fnName, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
if arch == "" {
|
||||
// Determine architecture from +build line if possible.
|
||||
if m := asmPlusBuild.FindStringSubmatch(line); m != nil {
|
||||
// There can be multiple architectures in a single +build line,
|
||||
// so accumulate them all and then prefer the one that
|
||||
// matches build.Default.GOARCH.
|
||||
var archCandidates []*asmArch
|
||||
for _, fld := range strings.Fields(m[1]) {
|
||||
for _, a := range arches {
|
||||
if a.name == fld {
|
||||
archCandidates = append(archCandidates, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, a := range archCandidates {
|
||||
if a.name == build.Default.GOARCH {
|
||||
archCandidates = []*asmArch{a}
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(archCandidates) > 0 {
|
||||
arch = archCandidates[0].name
|
||||
archDef = archCandidates[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if m := asmTEXT.FindStringSubmatch(line); m != nil {
|
||||
flushRet()
|
||||
if arch == "" {
|
||||
// Arch not specified by filename or build tags.
|
||||
// Fall back to build.Default.GOARCH.
|
||||
for _, a := range arches {
|
||||
if a.name == build.Default.GOARCH {
|
||||
arch = a.name
|
||||
archDef = a
|
||||
break
|
||||
}
|
||||
}
|
||||
if arch == "" {
|
||||
log.Printf("%s: cannot determine architecture for assembly file", fname)
|
||||
continue Files
|
||||
}
|
||||
}
|
||||
fnName = m[2]
|
||||
if pkgPath := strings.TrimSpace(m[1]); pkgPath != "" {
|
||||
// The assembler uses Unicode division slash within
|
||||
// identifiers to represent the directory separator.
|
||||
pkgPath = strings.Replace(pkgPath, "∕", "/", -1)
|
||||
if pkgPath != pass.Pkg.Path() {
|
||||
log.Printf("%s:%d: [%s] cannot check cross-package assembly function: %s is in package %s", fname, lineno, arch, fnName, pkgPath)
|
||||
fn = nil
|
||||
fnName = ""
|
||||
continue
|
||||
}
|
||||
}
|
||||
flag := m[3]
|
||||
fn = knownFunc[fnName][arch]
|
||||
if fn != nil {
|
||||
size, _ := strconv.Atoi(m[5])
|
||||
if size != fn.size && (flag != "7" && !strings.Contains(flag, "NOSPLIT") || size != 0) {
|
||||
badf("wrong argument size %d; expected $...-%d", size, fn.size)
|
||||
}
|
||||
}
|
||||
localSize, _ = strconv.Atoi(m[4])
|
||||
localSize += archDef.intSize
|
||||
if archDef.lr && !strings.Contains(flag, "NOFRAME") {
|
||||
// Account for caller's saved LR
|
||||
localSize += archDef.intSize
|
||||
}
|
||||
argSize, _ = strconv.Atoi(m[5])
|
||||
if fn == nil && !strings.Contains(fnName, "<>") {
|
||||
badf("function %s missing Go declaration", fnName)
|
||||
}
|
||||
wroteSP = false
|
||||
haveRetArg = false
|
||||
continue
|
||||
} else if strings.Contains(line, "TEXT") && strings.Contains(line, "SB") {
|
||||
// function, but not visible from Go (didn't match asmTEXT), so stop checking
|
||||
flushRet()
|
||||
fn = nil
|
||||
fnName = ""
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(line, "RET") {
|
||||
retLine = append(retLine, lineno)
|
||||
}
|
||||
|
||||
if fnName == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if asmDATA.FindStringSubmatch(line) != nil {
|
||||
fn = nil
|
||||
}
|
||||
|
||||
if archDef == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(line, ", "+archDef.stack) || strings.Contains(line, ",\t"+archDef.stack) {
|
||||
wroteSP = true
|
||||
continue
|
||||
}
|
||||
|
||||
for _, m := range asmSP.FindAllStringSubmatch(line, -1) {
|
||||
if m[3] != archDef.stack || wroteSP {
|
||||
continue
|
||||
}
|
||||
off := 0
|
||||
if m[1] != "" {
|
||||
off, _ = strconv.Atoi(m[2])
|
||||
}
|
||||
if off >= localSize {
|
||||
if fn != nil {
|
||||
v := fn.varByOffset[off-localSize]
|
||||
if v != nil {
|
||||
badf("%s should be %s+%d(FP)", m[1], v.name, off-localSize)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if off >= localSize+argSize {
|
||||
badf("use of %s points beyond argument frame", m[1])
|
||||
continue
|
||||
}
|
||||
badf("use of %s to access argument frame", m[1])
|
||||
}
|
||||
}
|
||||
|
||||
if fn == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, m := range asmUnnamedFP.FindAllStringSubmatch(line, -1) {
|
||||
off, _ := strconv.Atoi(m[2])
|
||||
v := fn.varByOffset[off]
|
||||
if v != nil {
|
||||
badf("use of unnamed argument %s; offset %d is %s+%d(FP)", m[1], off, v.name, v.off)
|
||||
} else {
|
||||
badf("use of unnamed argument %s", m[1])
|
||||
}
|
||||
}
|
||||
|
||||
for _, m := range asmNamedFP.FindAllStringSubmatch(line, -1) {
|
||||
name := m[1]
|
||||
off := 0
|
||||
if m[2] != "" {
|
||||
off, _ = strconv.Atoi(m[2])
|
||||
}
|
||||
if name == "ret" || strings.HasPrefix(name, "ret_") {
|
||||
haveRetArg = true
|
||||
}
|
||||
v := fn.vars[name]
|
||||
if v == nil {
|
||||
// Allow argframe+0(FP).
|
||||
if name == "argframe" && off == 0 {
|
||||
continue
|
||||
}
|
||||
v = fn.varByOffset[off]
|
||||
if v != nil {
|
||||
badf("unknown variable %s; offset %d is %s+%d(FP)", name, off, v.name, v.off)
|
||||
} else {
|
||||
badf("unknown variable %s", name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
asmCheckVar(badf, fn, line, m[0], off, v)
|
||||
}
|
||||
}
|
||||
flushRet()
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func asmKindForType(t types.Type, size int) asmKind {
|
||||
switch t := t.Underlying().(type) {
|
||||
case *types.Basic:
|
||||
switch t.Kind() {
|
||||
case types.String:
|
||||
return asmString
|
||||
case types.Complex64, types.Complex128:
|
||||
return asmComplex
|
||||
}
|
||||
return asmKind(size)
|
||||
case *types.Pointer, *types.Chan, *types.Map, *types.Signature:
|
||||
return asmKind(size)
|
||||
case *types.Struct:
|
||||
return asmStruct
|
||||
case *types.Interface:
|
||||
if t.Empty() {
|
||||
return asmEmptyInterface
|
||||
}
|
||||
return asmInterface
|
||||
case *types.Array:
|
||||
return asmArray
|
||||
case *types.Slice:
|
||||
return asmSlice
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// A component is an assembly-addressable component of a composite type,
|
||||
// or a composite type itself.
|
||||
type component struct {
|
||||
size int
|
||||
offset int
|
||||
kind asmKind
|
||||
typ string
|
||||
suffix string // Such as _base for string base, _0_lo for lo half of first element of [1]uint64 on 32 bit machine.
|
||||
outer string // The suffix for immediately containing composite type.
|
||||
}
|
||||
|
||||
func newComponent(suffix string, kind asmKind, typ string, offset, size int, outer string) component {
|
||||
return component{suffix: suffix, kind: kind, typ: typ, offset: offset, size: size, outer: outer}
|
||||
}
|
||||
|
||||
// componentsOfType generates a list of components of type t.
|
||||
// For example, given string, the components are the string itself, the base, and the length.
|
||||
func componentsOfType(arch *asmArch, t types.Type) []component {
|
||||
return appendComponentsRecursive(arch, t, nil, "", 0)
|
||||
}
|
||||
|
||||
// appendComponentsRecursive implements componentsOfType.
|
||||
// Recursion is required to correct handle structs and arrays,
|
||||
// which can contain arbitrary other types.
|
||||
func appendComponentsRecursive(arch *asmArch, t types.Type, cc []component, suffix string, off int) []component {
|
||||
s := t.String()
|
||||
size := int(arch.sizes.Sizeof(t))
|
||||
kind := asmKindForType(t, size)
|
||||
cc = append(cc, newComponent(suffix, kind, s, off, size, suffix))
|
||||
|
||||
switch kind {
|
||||
case 8:
|
||||
if arch.ptrSize == 4 {
|
||||
w1, w2 := "lo", "hi"
|
||||
if arch.bigEndian {
|
||||
w1, w2 = w2, w1
|
||||
}
|
||||
cc = append(cc, newComponent(suffix+"_"+w1, 4, "half "+s, off, 4, suffix))
|
||||
cc = append(cc, newComponent(suffix+"_"+w2, 4, "half "+s, off+4, 4, suffix))
|
||||
}
|
||||
|
||||
case asmEmptyInterface:
|
||||
cc = append(cc, newComponent(suffix+"_type", asmKind(arch.ptrSize), "interface type", off, arch.ptrSize, suffix))
|
||||
cc = append(cc, newComponent(suffix+"_data", asmKind(arch.ptrSize), "interface data", off+arch.ptrSize, arch.ptrSize, suffix))
|
||||
|
||||
case asmInterface:
|
||||
cc = append(cc, newComponent(suffix+"_itable", asmKind(arch.ptrSize), "interface itable", off, arch.ptrSize, suffix))
|
||||
cc = append(cc, newComponent(suffix+"_data", asmKind(arch.ptrSize), "interface data", off+arch.ptrSize, arch.ptrSize, suffix))
|
||||
|
||||
case asmSlice:
|
||||
cc = append(cc, newComponent(suffix+"_base", asmKind(arch.ptrSize), "slice base", off, arch.ptrSize, suffix))
|
||||
cc = append(cc, newComponent(suffix+"_len", asmKind(arch.intSize), "slice len", off+arch.ptrSize, arch.intSize, suffix))
|
||||
cc = append(cc, newComponent(suffix+"_cap", asmKind(arch.intSize), "slice cap", off+arch.ptrSize+arch.intSize, arch.intSize, suffix))
|
||||
|
||||
case asmString:
|
||||
cc = append(cc, newComponent(suffix+"_base", asmKind(arch.ptrSize), "string base", off, arch.ptrSize, suffix))
|
||||
cc = append(cc, newComponent(suffix+"_len", asmKind(arch.intSize), "string len", off+arch.ptrSize, arch.intSize, suffix))
|
||||
|
||||
case asmComplex:
|
||||
fsize := size / 2
|
||||
cc = append(cc, newComponent(suffix+"_real", asmKind(fsize), fmt.Sprintf("real(complex%d)", size*8), off, fsize, suffix))
|
||||
cc = append(cc, newComponent(suffix+"_imag", asmKind(fsize), fmt.Sprintf("imag(complex%d)", size*8), off+fsize, fsize, suffix))
|
||||
|
||||
case asmStruct:
|
||||
tu := t.Underlying().(*types.Struct)
|
||||
fields := make([]*types.Var, tu.NumFields())
|
||||
for i := 0; i < tu.NumFields(); i++ {
|
||||
fields[i] = tu.Field(i)
|
||||
}
|
||||
offsets := arch.sizes.Offsetsof(fields)
|
||||
for i, f := range fields {
|
||||
cc = appendComponentsRecursive(arch, f.Type(), cc, suffix+"_"+f.Name(), off+int(offsets[i]))
|
||||
}
|
||||
|
||||
case asmArray:
|
||||
tu := t.Underlying().(*types.Array)
|
||||
elem := tu.Elem()
|
||||
// Calculate offset of each element array.
|
||||
fields := []*types.Var{
|
||||
types.NewVar(token.NoPos, nil, "fake0", elem),
|
||||
types.NewVar(token.NoPos, nil, "fake1", elem),
|
||||
}
|
||||
offsets := arch.sizes.Offsetsof(fields)
|
||||
elemoff := int(offsets[1])
|
||||
for i := 0; i < int(tu.Len()); i++ {
|
||||
cc = appendComponentsRecursive(arch, elem, cc, suffix+"_"+strconv.Itoa(i), i*elemoff)
|
||||
}
|
||||
}
|
||||
|
||||
return cc
|
||||
}
|
||||
|
||||
// asmParseDecl parses a function decl for expected assembly variables.
|
||||
func asmParseDecl(pass *analysis.Pass, decl *ast.FuncDecl) map[string]*asmFunc {
|
||||
var (
|
||||
arch *asmArch
|
||||
fn *asmFunc
|
||||
offset int
|
||||
)
|
||||
|
||||
// addParams adds asmVars for each of the parameters in list.
|
||||
// isret indicates whether the list are the arguments or the return values.
|
||||
// TODO(adonovan): simplify by passing (*types.Signature).{Params,Results}
|
||||
// instead of list.
|
||||
addParams := func(list []*ast.Field, isret bool) {
|
||||
argnum := 0
|
||||
for _, fld := range list {
|
||||
t := pass.TypesInfo.Types[fld.Type].Type
|
||||
|
||||
// Work around github.com/golang/go/issues/28277.
|
||||
if t == nil {
|
||||
if ell, ok := fld.Type.(*ast.Ellipsis); ok {
|
||||
t = types.NewSlice(pass.TypesInfo.Types[ell.Elt].Type)
|
||||
}
|
||||
}
|
||||
|
||||
align := int(arch.sizes.Alignof(t))
|
||||
size := int(arch.sizes.Sizeof(t))
|
||||
offset += -offset & (align - 1)
|
||||
cc := componentsOfType(arch, t)
|
||||
|
||||
// names is the list of names with this type.
|
||||
names := fld.Names
|
||||
if len(names) == 0 {
|
||||
// Anonymous args will be called arg, arg1, arg2, ...
|
||||
// Similarly so for return values: ret, ret1, ret2, ...
|
||||
name := "arg"
|
||||
if isret {
|
||||
name = "ret"
|
||||
}
|
||||
if argnum > 0 {
|
||||
name += strconv.Itoa(argnum)
|
||||
}
|
||||
names = []*ast.Ident{ast.NewIdent(name)}
|
||||
}
|
||||
argnum += len(names)
|
||||
|
||||
// Create variable for each name.
|
||||
for _, id := range names {
|
||||
name := id.Name
|
||||
for _, c := range cc {
|
||||
outer := name + c.outer
|
||||
v := asmVar{
|
||||
name: name + c.suffix,
|
||||
kind: c.kind,
|
||||
typ: c.typ,
|
||||
off: offset + c.offset,
|
||||
size: c.size,
|
||||
}
|
||||
if vo := fn.vars[outer]; vo != nil {
|
||||
vo.inner = append(vo.inner, &v)
|
||||
}
|
||||
fn.vars[v.name] = &v
|
||||
for i := 0; i < v.size; i++ {
|
||||
fn.varByOffset[v.off+i] = &v
|
||||
}
|
||||
}
|
||||
offset += size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m := make(map[string]*asmFunc)
|
||||
for _, arch = range arches {
|
||||
fn = &asmFunc{
|
||||
arch: arch,
|
||||
vars: make(map[string]*asmVar),
|
||||
varByOffset: make(map[int]*asmVar),
|
||||
}
|
||||
offset = 0
|
||||
addParams(decl.Type.Params.List, false)
|
||||
if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 {
|
||||
offset += -offset & (arch.maxAlign - 1)
|
||||
addParams(decl.Type.Results.List, true)
|
||||
}
|
||||
fn.size = offset
|
||||
m[arch.name] = fn
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// asmCheckVar checks a single variable reference.
|
||||
func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr string, off int, v *asmVar) {
|
||||
m := asmOpcode.FindStringSubmatch(line)
|
||||
if m == nil {
|
||||
if !strings.HasPrefix(strings.TrimSpace(line), "//") {
|
||||
badf("cannot find assembly opcode")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Determine operand sizes from instruction.
|
||||
// Typically the suffix suffices, but there are exceptions.
|
||||
var src, dst, kind asmKind
|
||||
op := m[1]
|
||||
switch fn.arch.name + "." + op {
|
||||
case "386.FMOVLP":
|
||||
src, dst = 8, 4
|
||||
case "arm.MOVD":
|
||||
src = 8
|
||||
case "arm.MOVW":
|
||||
src = 4
|
||||
case "arm.MOVH", "arm.MOVHU":
|
||||
src = 2
|
||||
case "arm.MOVB", "arm.MOVBU":
|
||||
src = 1
|
||||
// LEA* opcodes don't really read the second arg.
|
||||
// They just take the address of it.
|
||||
case "386.LEAL":
|
||||
dst = 4
|
||||
case "amd64.LEAQ":
|
||||
dst = 8
|
||||
case "amd64p32.LEAL":
|
||||
dst = 4
|
||||
default:
|
||||
switch fn.arch.name {
|
||||
case "386", "amd64":
|
||||
if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "D") || strings.HasSuffix(op, "DP")) {
|
||||
// FMOVDP, FXCHD, etc
|
||||
src = 8
|
||||
break
|
||||
}
|
||||
if strings.HasPrefix(op, "P") && strings.HasSuffix(op, "RD") {
|
||||
// PINSRD, PEXTRD, etc
|
||||
src = 4
|
||||
break
|
||||
}
|
||||
if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "F") || strings.HasSuffix(op, "FP")) {
|
||||
// FMOVFP, FXCHF, etc
|
||||
src = 4
|
||||
break
|
||||
}
|
||||
if strings.HasSuffix(op, "SD") {
|
||||
// MOVSD, SQRTSD, etc
|
||||
src = 8
|
||||
break
|
||||
}
|
||||
if strings.HasSuffix(op, "SS") {
|
||||
// MOVSS, SQRTSS, etc
|
||||
src = 4
|
||||
break
|
||||
}
|
||||
if strings.HasPrefix(op, "SET") {
|
||||
// SETEQ, etc
|
||||
src = 1
|
||||
break
|
||||
}
|
||||
switch op[len(op)-1] {
|
||||
case 'B':
|
||||
src = 1
|
||||
case 'W':
|
||||
src = 2
|
||||
case 'L':
|
||||
src = 4
|
||||
case 'D', 'Q':
|
||||
src = 8
|
||||
}
|
||||
case "ppc64", "ppc64le":
|
||||
// Strip standard suffixes to reveal size letter.
|
||||
m := ppc64Suff.FindStringSubmatch(op)
|
||||
if m != nil {
|
||||
switch m[1][0] {
|
||||
case 'B':
|
||||
src = 1
|
||||
case 'H':
|
||||
src = 2
|
||||
case 'W':
|
||||
src = 4
|
||||
case 'D':
|
||||
src = 8
|
||||
}
|
||||
}
|
||||
case "mips", "mipsle", "mips64", "mips64le":
|
||||
switch op {
|
||||
case "MOVB", "MOVBU":
|
||||
src = 1
|
||||
case "MOVH", "MOVHU":
|
||||
src = 2
|
||||
case "MOVW", "MOVWU", "MOVF":
|
||||
src = 4
|
||||
case "MOVV", "MOVD":
|
||||
src = 8
|
||||
}
|
||||
case "s390x":
|
||||
switch op {
|
||||
case "MOVB", "MOVBZ":
|
||||
src = 1
|
||||
case "MOVH", "MOVHZ":
|
||||
src = 2
|
||||
case "MOVW", "MOVWZ", "FMOVS":
|
||||
src = 4
|
||||
case "MOVD", "FMOVD":
|
||||
src = 8
|
||||
}
|
||||
}
|
||||
}
|
||||
if dst == 0 {
|
||||
dst = src
|
||||
}
|
||||
|
||||
// Determine whether the match we're holding
|
||||
// is the first or second argument.
|
||||
if strings.Index(line, expr) > strings.Index(line, ",") {
|
||||
kind = dst
|
||||
} else {
|
||||
kind = src
|
||||
}
|
||||
|
||||
vk := v.kind
|
||||
vs := v.size
|
||||
vt := v.typ
|
||||
switch vk {
|
||||
case asmInterface, asmEmptyInterface, asmString, asmSlice:
|
||||
// allow reference to first word (pointer)
|
||||
vk = v.inner[0].kind
|
||||
vs = v.inner[0].size
|
||||
vt = v.inner[0].typ
|
||||
}
|
||||
|
||||
if off != v.off {
|
||||
var inner bytes.Buffer
|
||||
for i, vi := range v.inner {
|
||||
if len(v.inner) > 1 {
|
||||
fmt.Fprintf(&inner, ",")
|
||||
}
|
||||
fmt.Fprintf(&inner, " ")
|
||||
if i == len(v.inner)-1 {
|
||||
fmt.Fprintf(&inner, "or ")
|
||||
}
|
||||
fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
|
||||
}
|
||||
badf("invalid offset %s; expected %s+%d(FP)%s", expr, v.name, v.off, inner.String())
|
||||
return
|
||||
}
|
||||
if kind != 0 && kind != vk {
|
||||
var inner bytes.Buffer
|
||||
if len(v.inner) > 0 {
|
||||
fmt.Fprintf(&inner, " containing")
|
||||
for i, vi := range v.inner {
|
||||
if i > 0 && len(v.inner) > 2 {
|
||||
fmt.Fprintf(&inner, ",")
|
||||
}
|
||||
fmt.Fprintf(&inner, " ")
|
||||
if i > 0 && i == len(v.inner)-1 {
|
||||
fmt.Fprintf(&inner, "and ")
|
||||
}
|
||||
fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
|
||||
}
|
||||
}
|
||||
badf("invalid %s of %s; %s is %d-byte value%s", op, expr, vt, vs, inner.String())
|
||||
}
|
||||
}
|
||||
17
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl_test.go
generated
vendored
Normal file
17
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl_test.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
package asmdecl_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
"golang.org/x/tools/go/analysis/passes/asmdecl"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
testdata := analysistest.TestData()
|
||||
analysistest.Run(t, testdata, asmdecl.Analyzer, "a")
|
||||
}
|
||||
48
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm.go
generated
vendored
Normal file
48
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright 2010 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.
|
||||
|
||||
// This file contains declarations to test the assembly in test_asm.s.
|
||||
|
||||
package a
|
||||
|
||||
type S struct {
|
||||
i int32
|
||||
b bool
|
||||
s string
|
||||
}
|
||||
|
||||
func arg1(x int8, y uint8)
|
||||
func arg2(x int16, y uint16)
|
||||
func arg4(x int32, y uint32)
|
||||
func arg8(x int64, y uint64)
|
||||
func argint(x int, y uint)
|
||||
func argptr(x *byte, y *byte, c chan int, m map[int]int, f func())
|
||||
func argstring(x, y string)
|
||||
func argslice(x, y []string)
|
||||
func argiface(x interface{}, y interface {
|
||||
m()
|
||||
})
|
||||
func argcomplex(x complex64, y complex128)
|
||||
func argstruct(x S, y struct{})
|
||||
func argarray(x [2]S)
|
||||
func returnint() int
|
||||
func returnbyte(x int) byte
|
||||
func returnnamed(x byte) (r1 int, r2 int16, r3 string, r4 byte)
|
||||
func returnintmissing() int
|
||||
func leaf(x, y int) int
|
||||
|
||||
func noprof(x int)
|
||||
func dupok(x int)
|
||||
func nosplit(x int)
|
||||
func rodata(x int)
|
||||
func noptr(x int)
|
||||
func wrapper(x int)
|
||||
|
||||
func f15271() (x uint32)
|
||||
func f17584(x float32, y complex64)
|
||||
|
||||
func noframe1(x int32)
|
||||
func noframe2(x int32)
|
||||
|
||||
func fvariadic(int, ...int)
|
||||
314
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm1.s
generated
vendored
Normal file
314
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm1.s
generated
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
// Copyright 2013 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 amd64
|
||||
|
||||
TEXT ·arg1(SB),0,$0-2
|
||||
MOVB x+0(FP), AX
|
||||
// MOVB x+0(FP), AX // commented out instructions used to panic
|
||||
MOVB y+1(FP), BX
|
||||
MOVW x+0(FP), AX // want `\[amd64\] arg1: invalid MOVW of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVW y+1(FP), AX // want `invalid MOVW of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVL x+0(FP), AX // want `invalid MOVL of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVL y+1(FP), AX // want `invalid MOVL of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVQ y+1(FP), AX // want `invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVB x+1(FP), AX // want `invalid offset x\+1\(FP\); expected x\+0\(FP\)`
|
||||
MOVB y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+1\(FP\)`
|
||||
TESTB x+0(FP), AX
|
||||
TESTB y+1(FP), BX
|
||||
TESTW x+0(FP), AX // want `invalid TESTW of x\+0\(FP\); int8 is 1-byte value`
|
||||
TESTW y+1(FP), AX // want `invalid TESTW of y\+1\(FP\); uint8 is 1-byte value`
|
||||
TESTL x+0(FP), AX // want `invalid TESTL of x\+0\(FP\); int8 is 1-byte value`
|
||||
TESTL y+1(FP), AX // want `invalid TESTL of y\+1\(FP\); uint8 is 1-byte value`
|
||||
TESTQ x+0(FP), AX // want `invalid TESTQ of x\+0\(FP\); int8 is 1-byte value`
|
||||
TESTQ y+1(FP), AX // want `invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value`
|
||||
TESTB x+1(FP), AX // want `invalid offset x\+1\(FP\); expected x\+0\(FP\)`
|
||||
TESTB y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+1\(FP\)`
|
||||
MOVB 8(SP), AX // want `8\(SP\) should be x\+0\(FP\)`
|
||||
MOVB 9(SP), AX // want `9\(SP\) should be y\+1\(FP\)`
|
||||
MOVB 10(SP), AX // want `use of 10\(SP\) points beyond argument frame`
|
||||
RET
|
||||
|
||||
TEXT ·arg2(SB),0,$0-4
|
||||
MOVB x+0(FP), AX // want `arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVB y+2(FP), AX // want `invalid MOVB of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVW x+0(FP), AX
|
||||
MOVW y+2(FP), BX
|
||||
MOVL x+0(FP), AX // want `invalid MOVL of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVL y+2(FP), AX // want `invalid MOVL of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVQ y+2(FP), AX // want `invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVW x+2(FP), AX // want `invalid offset x\+2\(FP\); expected x\+0\(FP\)`
|
||||
MOVW y+0(FP), AX // want `invalid offset y\+0\(FP\); expected y\+2\(FP\)`
|
||||
TESTB x+0(FP), AX // want `invalid TESTB of x\+0\(FP\); int16 is 2-byte value`
|
||||
TESTB y+2(FP), AX // want `invalid TESTB of y\+2\(FP\); uint16 is 2-byte value`
|
||||
TESTW x+0(FP), AX
|
||||
TESTW y+2(FP), BX
|
||||
TESTL x+0(FP), AX // want `invalid TESTL of x\+0\(FP\); int16 is 2-byte value`
|
||||
TESTL y+2(FP), AX // want `invalid TESTL of y\+2\(FP\); uint16 is 2-byte value`
|
||||
TESTQ x+0(FP), AX // want `invalid TESTQ of x\+0\(FP\); int16 is 2-byte value`
|
||||
TESTQ y+2(FP), AX // want `invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value`
|
||||
TESTW x+2(FP), AX // want `invalid offset x\+2\(FP\); expected x\+0\(FP\)`
|
||||
TESTW y+0(FP), AX // want `invalid offset y\+0\(FP\); expected y\+2\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \$\.\.\.-8`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVB y+4(FP), BX // want `invalid MOVB of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVW y+4(FP), AX // want `invalid MOVW of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVL x+0(FP), AX
|
||||
MOVL y+4(FP), AX
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVQ y+4(FP), AX // want `invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVL x+4(FP), AX // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVL y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
TESTB x+0(FP), AX // want `invalid TESTB of x\+0\(FP\); int32 is 4-byte value`
|
||||
TESTB y+4(FP), BX // want `invalid TESTB of y\+4\(FP\); uint32 is 4-byte value`
|
||||
TESTW x+0(FP), AX // want `invalid TESTW of x\+0\(FP\); int32 is 4-byte value`
|
||||
TESTW y+4(FP), AX // want `invalid TESTW of y\+4\(FP\); uint32 is 4-byte value`
|
||||
TESTL x+0(FP), AX
|
||||
TESTL y+4(FP), AX
|
||||
TESTQ x+0(FP), AX // want `invalid TESTQ of x\+0\(FP\); int32 is 4-byte value`
|
||||
TESTQ y+4(FP), AX // want `invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value`
|
||||
TESTL x+4(FP), AX // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
TESTL y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-16`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVB y+8(FP), BX // want `invalid MOVB of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVW y+8(FP), AX // want `invalid MOVW of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVL x+0(FP), AX // want `invalid MOVL of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVL y+8(FP), AX // want `invalid MOVL of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVQ x+0(FP), AX
|
||||
MOVQ y+8(FP), AX
|
||||
MOVQ x+8(FP), AX // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
TESTB x+0(FP), AX // want `invalid TESTB of x\+0\(FP\); int64 is 8-byte value`
|
||||
TESTB y+8(FP), BX // want `invalid TESTB of y\+8\(FP\); uint64 is 8-byte value`
|
||||
TESTW x+0(FP), AX // want `invalid TESTW of x\+0\(FP\); int64 is 8-byte value`
|
||||
TESTW y+8(FP), AX // want `invalid TESTW of y\+8\(FP\); uint64 is 8-byte value`
|
||||
TESTL x+0(FP), AX // want `invalid TESTL of x\+0\(FP\); int64 is 8-byte value`
|
||||
TESTL y+8(FP), AX // want `invalid TESTL of y\+8\(FP\); uint64 is 8-byte value`
|
||||
TESTQ x+0(FP), AX
|
||||
TESTQ y+8(FP), AX
|
||||
TESTQ x+8(FP), AX // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
TESTQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \$\.\.\.-16`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); int is 8-byte value`
|
||||
MOVB y+8(FP), BX // want `invalid MOVB of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); int is 8-byte value`
|
||||
MOVW y+8(FP), AX // want `invalid MOVW of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVL x+0(FP), AX // want `invalid MOVL of x\+0\(FP\); int is 8-byte value`
|
||||
MOVL y+8(FP), AX // want `invalid MOVL of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVQ x+0(FP), AX
|
||||
MOVQ y+8(FP), AX
|
||||
MOVQ x+8(FP), AX // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
TESTB x+0(FP), AX // want `invalid TESTB of x\+0\(FP\); int is 8-byte value`
|
||||
TESTB y+8(FP), BX // want `invalid TESTB of y\+8\(FP\); uint is 8-byte value`
|
||||
TESTW x+0(FP), AX // want `invalid TESTW of x\+0\(FP\); int is 8-byte value`
|
||||
TESTW y+8(FP), AX // want `invalid TESTW of y\+8\(FP\); uint is 8-byte value`
|
||||
TESTL x+0(FP), AX // want `invalid TESTL of x\+0\(FP\); int is 8-byte value`
|
||||
TESTL y+8(FP), AX // want `invalid TESTL of y\+8\(FP\); uint is 8-byte value`
|
||||
TESTQ x+0(FP), AX
|
||||
TESTQ y+8(FP), AX
|
||||
TESTQ x+8(FP), AX // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
TESTQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-40`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVB y+8(FP), BX // want `invalid MOVB of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVW y+8(FP), AX // want `invalid MOVW of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVL x+0(FP), AX // want `invalid MOVL of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVL y+8(FP), AX // want `invalid MOVL of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVQ x+0(FP), AX
|
||||
MOVQ y+8(FP), AX
|
||||
MOVQ x+8(FP), AX // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
TESTB x+0(FP), AX // want `invalid TESTB of x\+0\(FP\); \*byte is 8-byte value`
|
||||
TESTB y+8(FP), BX // want `invalid TESTB of y\+8\(FP\); \*byte is 8-byte value`
|
||||
TESTW x+0(FP), AX // want `invalid TESTW of x\+0\(FP\); \*byte is 8-byte value`
|
||||
TESTW y+8(FP), AX // want `invalid TESTW of y\+8\(FP\); \*byte is 8-byte value`
|
||||
TESTL x+0(FP), AX // want `invalid TESTL of x\+0\(FP\); \*byte is 8-byte value`
|
||||
TESTL y+8(FP), AX // want `invalid TESTL of y\+8\(FP\); \*byte is 8-byte value`
|
||||
TESTQ x+0(FP), AX
|
||||
TESTQ y+8(FP), AX
|
||||
TESTQ x+8(FP), AX // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
TESTQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
MOVL c+16(FP), AX // want `invalid MOVL of c\+16\(FP\); chan int is 8-byte value`
|
||||
MOVL m+24(FP), AX // want `invalid MOVL of m\+24\(FP\); map\[int\]int is 8-byte value`
|
||||
MOVL f+32(FP), AX // want `invalid MOVL of f\+32\(FP\); func\(\) is 8-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·argstring(SB),0,$32 // want `wrong argument size 0; expected \$\.\.\.-32`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); string base is 8-byte value`
|
||||
MOVL x+0(FP), AX // want `invalid MOVL of x\+0\(FP\); string base is 8-byte value`
|
||||
MOVQ x+0(FP), AX
|
||||
MOVW x_base+0(FP), AX // want `invalid MOVW of x_base\+0\(FP\); string base is 8-byte value`
|
||||
MOVL x_base+0(FP), AX // want `invalid MOVL of x_base\+0\(FP\); string base is 8-byte value`
|
||||
MOVQ x_base+0(FP), AX
|
||||
MOVW x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVL x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVQ x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVW x_len+8(FP), AX // want `invalid MOVW of x_len\+8\(FP\); string len is 8-byte value`
|
||||
MOVL x_len+8(FP), AX // want `invalid MOVL of x_len\+8\(FP\); string len is 8-byte value`
|
||||
MOVQ x_len+8(FP), AX
|
||||
MOVQ y+0(FP), AX // want `invalid offset y\+0\(FP\); expected y\+16\(FP\)`
|
||||
MOVQ y_len+8(FP), AX // want `invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argslice(SB),0,$48 // want `wrong argument size 0; expected \$\.\.\.-48`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); slice base is 8-byte value`
|
||||
MOVL x+0(FP), AX // want `invalid MOVL of x\+0\(FP\); slice base is 8-byte value`
|
||||
MOVQ x+0(FP), AX
|
||||
MOVW x_base+0(FP), AX // want `invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value`
|
||||
MOVL x_base+0(FP), AX // want `invalid MOVL of x_base\+0\(FP\); slice base is 8-byte value`
|
||||
MOVQ x_base+0(FP), AX
|
||||
MOVW x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVL x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVQ x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVW x_len+8(FP), AX // want `invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value`
|
||||
MOVL x_len+8(FP), AX // want `invalid MOVL of x_len\+8\(FP\); slice len is 8-byte value`
|
||||
MOVQ x_len+8(FP), AX
|
||||
MOVW x_cap+0(FP), AX // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVL x_cap+0(FP), AX // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVQ x_cap+0(FP), AX // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVW x_cap+16(FP), AX // want `invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value`
|
||||
MOVL x_cap+16(FP), AX // want `invalid MOVL of x_cap\+16\(FP\); slice cap is 8-byte value`
|
||||
MOVQ x_cap+16(FP), AX
|
||||
MOVQ y+0(FP), AX // want `invalid offset y\+0\(FP\); expected y\+24\(FP\)`
|
||||
MOVQ y_len+8(FP), AX // want `invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)`
|
||||
MOVQ y_cap+16(FP), AX // want `invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argiface(SB),0,$0-32
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); interface type is 8-byte value`
|
||||
MOVL x+0(FP), AX // want `invalid MOVL of x\+0\(FP\); interface type is 8-byte value`
|
||||
MOVQ x+0(FP), AX
|
||||
MOVW x_type+0(FP), AX // want `invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value`
|
||||
MOVL x_type+0(FP), AX // want `invalid MOVL of x_type\+0\(FP\); interface type is 8-byte value`
|
||||
MOVQ x_type+0(FP), AX
|
||||
MOVQ x_itable+0(FP), AX // want `unknown variable x_itable; offset 0 is x_type\+0\(FP\)`
|
||||
MOVQ x_itable+1(FP), AX // want `unknown variable x_itable; offset 1 is x_type\+0\(FP\)`
|
||||
MOVW x_data+0(FP), AX // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVL x_data+0(FP), AX // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVQ x_data+0(FP), AX // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVW x_data+8(FP), AX // want `invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value`
|
||||
MOVL x_data+8(FP), AX // want `invalid MOVL of x_data\+8\(FP\); interface data is 8-byte value`
|
||||
MOVQ x_data+8(FP), AX
|
||||
MOVW y+16(FP), AX // want `invalid MOVW of y\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVL y+16(FP), AX // want `invalid MOVL of y\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVQ y+16(FP), AX
|
||||
MOVW y_itable+16(FP), AX // want `invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVL y_itable+16(FP), AX // want `invalid MOVL of y_itable\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVQ y_itable+16(FP), AX
|
||||
MOVQ y_type+16(FP), AX // want `unknown variable y_type; offset 16 is y_itable\+16\(FP\)`
|
||||
MOVW y_data+16(FP), AX // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVL y_data+16(FP), AX // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVQ y_data+16(FP), AX // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVW y_data+24(FP), AX // want `invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value`
|
||||
MOVL y_data+24(FP), AX // want `invalid MOVL of y_data\+24\(FP\); interface data is 8-byte value`
|
||||
MOVQ y_data+24(FP), AX
|
||||
RET
|
||||
|
||||
TEXT ·argcomplex(SB),0,$24 // want `wrong argument size 0; expected \$\.\.\.-24`
|
||||
MOVSS x+0(FP), X0 // want `invalid MOVSS of x\+0\(FP\); complex64 is 8-byte value containing x_real\+0\(FP\) and x_imag\+4\(FP\)`
|
||||
MOVSD x+0(FP), X0 // want `invalid MOVSD of x\+0\(FP\); complex64 is 8-byte value containing x_real\+0\(FP\) and x_imag\+4\(FP\)`
|
||||
MOVSS x_real+0(FP), X0
|
||||
MOVSD x_real+0(FP), X0 // want `invalid MOVSD of x_real\+0\(FP\); real\(complex64\) is 4-byte value`
|
||||
MOVSS x_real+4(FP), X0 // want `invalid offset x_real\+4\(FP\); expected x_real\+0\(FP\)`
|
||||
MOVSS x_imag+4(FP), X0
|
||||
MOVSD x_imag+4(FP), X0 // want `invalid MOVSD of x_imag\+4\(FP\); imag\(complex64\) is 4-byte value`
|
||||
MOVSS x_imag+8(FP), X0 // want `invalid offset x_imag\+8\(FP\); expected x_imag\+4\(FP\)`
|
||||
MOVSD y+8(FP), X0 // want `invalid MOVSD of y\+8\(FP\); complex128 is 16-byte value containing y_real\+8\(FP\) and y_imag\+16\(FP\)`
|
||||
MOVSS y_real+8(FP), X0 // want `invalid MOVSS of y_real\+8\(FP\); real\(complex128\) is 8-byte value`
|
||||
MOVSD y_real+8(FP), X0
|
||||
MOVSS y_real+16(FP), X0 // want `invalid offset y_real\+16\(FP\); expected y_real\+8\(FP\)`
|
||||
MOVSS y_imag+16(FP), X0 // want `invalid MOVSS of y_imag\+16\(FP\); imag\(complex128\) is 8-byte value`
|
||||
MOVSD y_imag+16(FP), X0
|
||||
MOVSS y_imag+24(FP), X0 // want `invalid offset y_imag\+24\(FP\); expected y_imag\+16\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argstruct(SB),0,$64 // want `wrong argument size 0; expected \$\.\.\.-24`
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); a.S is 24-byte value`
|
||||
MOVQ x_i+0(FP), AX // want `invalid MOVQ of x_i\+0\(FP\); int32 is 4-byte value`
|
||||
MOVQ x_b+0(FP), AX // want `invalid offset x_b\+0\(FP\); expected x_b\+4\(FP\)`
|
||||
MOVQ x_s+8(FP), AX
|
||||
MOVQ x_s_base+8(FP), AX
|
||||
MOVQ x_s+16(FP), AX // want `invalid offset x_s\+16\(FP\); expected x_s\+8\(FP\), x_s_base\+8\(FP\), or x_s_len\+16\(FP\)`
|
||||
MOVQ x_s_len+16(FP), AX
|
||||
RET
|
||||
|
||||
TEXT ·argarray(SB),0,$64 // want `wrong argument size 0; expected \$\.\.\.-48`
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); \[2\]a.S is 48-byte value`
|
||||
MOVQ x_0_i+0(FP), AX // want `invalid MOVQ of x_0_i\+0\(FP\); int32 is 4-byte value`
|
||||
MOVQ x_0_b+0(FP), AX // want `invalid offset x_0_b\+0\(FP\); expected x_0_b\+4\(FP\)`
|
||||
MOVQ x_0_s+8(FP), AX
|
||||
MOVQ x_0_s_base+8(FP), AX
|
||||
MOVQ x_0_s+16(FP), AX // want `invalid offset x_0_s\+16\(FP\); expected x_0_s\+8\(FP\), x_0_s_base\+8\(FP\), or x_0_s_len\+16\(FP\)`
|
||||
MOVQ x_0_s_len+16(FP), AX
|
||||
MOVB foo+25(FP), AX // want `unknown variable foo; offset 25 is x_1_i\+24\(FP\)`
|
||||
MOVQ x_1_s+32(FP), AX
|
||||
MOVQ x_1_s_base+32(FP), AX
|
||||
MOVQ x_1_s+40(FP), AX // want `invalid offset x_1_s\+40\(FP\); expected x_1_s\+32\(FP\), x_1_s_base\+32\(FP\), or x_1_s_len\+40\(FP\)`
|
||||
MOVQ x_1_s_len+40(FP), AX
|
||||
RET
|
||||
|
||||
TEXT ·returnint(SB),0,$0-8
|
||||
MOVB AX, ret+0(FP) // want `invalid MOVB of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVW AX, ret+0(FP) // want `invalid MOVW of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVL AX, ret+0(FP) // want `invalid MOVL of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVQ AX, ret+0(FP)
|
||||
MOVQ AX, ret+1(FP) // want `invalid offset ret\+1\(FP\); expected ret\+0\(FP\)`
|
||||
MOVQ AX, r+0(FP) // want `unknown variable r; offset 0 is ret\+0\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnbyte(SB),0,$0-9
|
||||
MOVQ x+0(FP), AX
|
||||
MOVB AX, ret+8(FP)
|
||||
MOVW AX, ret+8(FP) // want `invalid MOVW of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVL AX, ret+8(FP) // want `invalid MOVL of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVQ AX, ret+8(FP) // want `invalid MOVQ of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVB AX, ret+7(FP) // want `invalid offset ret\+7\(FP\); expected ret\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnnamed(SB),0,$0-41
|
||||
MOVB x+0(FP), AX
|
||||
MOVQ AX, r1+8(FP)
|
||||
MOVW AX, r2+16(FP)
|
||||
MOVQ AX, r3+24(FP)
|
||||
MOVQ AX, r3_base+24(FP)
|
||||
MOVQ AX, r3_len+32(FP)
|
||||
MOVB AX, r4+40(FP)
|
||||
MOVL AX, r1+8(FP) // want `invalid MOVL of r1\+8\(FP\); int is 8-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·returnintmissing(SB),0,$0-8
|
||||
RET // want `RET without writing to 8-byte ret\+0\(FP\)`
|
||||
|
||||
|
||||
// issue 15271
|
||||
TEXT ·f15271(SB), NOSPLIT, $0-4
|
||||
// Stick 123 into the low 32 bits of X0.
|
||||
MOVQ $123, AX
|
||||
PINSRD $0, AX, X0
|
||||
|
||||
// Return them.
|
||||
PEXTRD $0, X0, x+0(FP)
|
||||
RET
|
||||
|
||||
// issue 17584
|
||||
TEXT ·f17584(SB), NOSPLIT, $12
|
||||
MOVSS x+0(FP), X0
|
||||
MOVSS y_real+4(FP), X0
|
||||
MOVSS y_imag+8(FP), X0
|
||||
RET
|
||||
256
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm2.s
generated
vendored
Normal file
256
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm2.s
generated
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
// Copyright 2013 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 386
|
||||
|
||||
TEXT ·arg1(SB),0,$0-2
|
||||
MOVB x+0(FP), AX
|
||||
MOVB y+1(FP), BX
|
||||
MOVW x+0(FP), AX // want `\[386\] arg1: invalid MOVW of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVW y+1(FP), AX // want `invalid MOVW of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVL x+0(FP), AX // want `invalid MOVL of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVL y+1(FP), AX // want `invalid MOVL of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVQ y+1(FP), AX // want `invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVB x+1(FP), AX // want `invalid offset x\+1\(FP\); expected x\+0\(FP\)`
|
||||
MOVB y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+1\(FP\)`
|
||||
TESTB x+0(FP), AX
|
||||
TESTB y+1(FP), BX
|
||||
TESTW x+0(FP), AX // want `invalid TESTW of x\+0\(FP\); int8 is 1-byte value`
|
||||
TESTW y+1(FP), AX // want `invalid TESTW of y\+1\(FP\); uint8 is 1-byte value`
|
||||
TESTL x+0(FP), AX // want `invalid TESTL of x\+0\(FP\); int8 is 1-byte value`
|
||||
TESTL y+1(FP), AX // want `invalid TESTL of y\+1\(FP\); uint8 is 1-byte value`
|
||||
TESTQ x+0(FP), AX // want `invalid TESTQ of x\+0\(FP\); int8 is 1-byte value`
|
||||
TESTQ y+1(FP), AX // want `invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value`
|
||||
TESTB x+1(FP), AX // want `invalid offset x\+1\(FP\); expected x\+0\(FP\)`
|
||||
TESTB y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+1\(FP\)`
|
||||
MOVB 4(SP), AX // want `4\(SP\) should be x\+0\(FP\)`
|
||||
MOVB 5(SP), AX // want `5\(SP\) should be y\+1\(FP\)`
|
||||
MOVB 6(SP), AX // want `use of 6\(SP\) points beyond argument frame`
|
||||
RET
|
||||
|
||||
TEXT ·arg2(SB),0,$0-4
|
||||
MOVB x+0(FP), AX // want `arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVB y+2(FP), AX // want `invalid MOVB of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVW x+0(FP), AX
|
||||
MOVW y+2(FP), BX
|
||||
MOVL x+0(FP), AX // want `invalid MOVL of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVL y+2(FP), AX // want `invalid MOVL of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVQ y+2(FP), AX // want `invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVW x+2(FP), AX // want `invalid offset x\+2\(FP\); expected x\+0\(FP\)`
|
||||
MOVW y+0(FP), AX // want `invalid offset y\+0\(FP\); expected y\+2\(FP\)`
|
||||
TESTB x+0(FP), AX // want `invalid TESTB of x\+0\(FP\); int16 is 2-byte value`
|
||||
TESTB y+2(FP), AX // want `invalid TESTB of y\+2\(FP\); uint16 is 2-byte value`
|
||||
TESTW x+0(FP), AX
|
||||
TESTW y+2(FP), BX
|
||||
TESTL x+0(FP), AX // want `invalid TESTL of x\+0\(FP\); int16 is 2-byte value`
|
||||
TESTL y+2(FP), AX // want `invalid TESTL of y\+2\(FP\); uint16 is 2-byte value`
|
||||
TESTQ x+0(FP), AX // want `invalid TESTQ of x\+0\(FP\); int16 is 2-byte value`
|
||||
TESTQ y+2(FP), AX // want `invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value`
|
||||
TESTW x+2(FP), AX // want `invalid offset x\+2\(FP\); expected x\+0\(FP\)`
|
||||
TESTW y+0(FP), AX // want `invalid offset y\+0\(FP\); expected y\+2\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \$\.\.\.-8`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVB y+4(FP), BX // want `invalid MOVB of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVW y+4(FP), AX // want `invalid MOVW of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVL x+0(FP), AX
|
||||
MOVL y+4(FP), AX
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVQ y+4(FP), AX // want `invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVL x+4(FP), AX // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVL y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
TESTB x+0(FP), AX // want `invalid TESTB of x\+0\(FP\); int32 is 4-byte value`
|
||||
TESTB y+4(FP), BX // want `invalid TESTB of y\+4\(FP\); uint32 is 4-byte value`
|
||||
TESTW x+0(FP), AX // want `invalid TESTW of x\+0\(FP\); int32 is 4-byte value`
|
||||
TESTW y+4(FP), AX // want `invalid TESTW of y\+4\(FP\); uint32 is 4-byte value`
|
||||
TESTL x+0(FP), AX
|
||||
TESTL y+4(FP), AX
|
||||
TESTQ x+0(FP), AX // want `invalid TESTQ of x\+0\(FP\); int32 is 4-byte value`
|
||||
TESTQ y+4(FP), AX // want `invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value`
|
||||
TESTL x+4(FP), AX // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
TESTL y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-16`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVB y+8(FP), BX // want `invalid MOVB of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVW y+8(FP), AX // want `invalid MOVW of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVL x+0(FP), AX // want `invalid MOVL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)`
|
||||
MOVL x_lo+0(FP), AX
|
||||
MOVL x_hi+4(FP), AX
|
||||
MOVL y+8(FP), AX // want `invalid MOVL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)`
|
||||
MOVL y_lo+8(FP), AX
|
||||
MOVL y_hi+12(FP), AX
|
||||
MOVQ x+0(FP), AX
|
||||
MOVQ y+8(FP), AX
|
||||
MOVQ x+8(FP), AX // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
TESTB x+0(FP), AX // want `invalid TESTB of x\+0\(FP\); int64 is 8-byte value`
|
||||
TESTB y+8(FP), BX // want `invalid TESTB of y\+8\(FP\); uint64 is 8-byte value`
|
||||
TESTW x+0(FP), AX // want `invalid TESTW of x\+0\(FP\); int64 is 8-byte value`
|
||||
TESTW y+8(FP), AX // want `invalid TESTW of y\+8\(FP\); uint64 is 8-byte value`
|
||||
TESTL x+0(FP), AX // want `invalid TESTL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)`
|
||||
TESTL y+8(FP), AX // want `invalid TESTL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)`
|
||||
TESTQ x+0(FP), AX
|
||||
TESTQ y+8(FP), AX
|
||||
TESTQ x+8(FP), AX // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
TESTQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \$\.\.\.-8`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); int is 4-byte value`
|
||||
MOVB y+4(FP), BX // want `invalid MOVB of y\+4\(FP\); uint is 4-byte value`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); int is 4-byte value`
|
||||
MOVW y+4(FP), AX // want `invalid MOVW of y\+4\(FP\); uint is 4-byte value`
|
||||
MOVL x+0(FP), AX
|
||||
MOVL y+4(FP), AX
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); int is 4-byte value`
|
||||
MOVQ y+4(FP), AX // want `invalid MOVQ of y\+4\(FP\); uint is 4-byte value`
|
||||
MOVQ x+4(FP), AX // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
TESTB x+0(FP), AX // want `invalid TESTB of x\+0\(FP\); int is 4-byte value`
|
||||
TESTB y+4(FP), BX // want `invalid TESTB of y\+4\(FP\); uint is 4-byte value`
|
||||
TESTW x+0(FP), AX // want `invalid TESTW of x\+0\(FP\); int is 4-byte value`
|
||||
TESTW y+4(FP), AX // want `invalid TESTW of y\+4\(FP\); uint is 4-byte value`
|
||||
TESTL x+0(FP), AX
|
||||
TESTL y+4(FP), AX
|
||||
TESTQ x+0(FP), AX // want `invalid TESTQ of x\+0\(FP\); int is 4-byte value`
|
||||
TESTQ y+4(FP), AX // want `invalid TESTQ of y\+4\(FP\); uint is 4-byte value`
|
||||
TESTQ x+4(FP), AX // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
TESTQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-20`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); \*byte is 4-byte value`
|
||||
MOVB y+4(FP), BX // want `invalid MOVB of y\+4\(FP\); \*byte is 4-byte value`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); \*byte is 4-byte value`
|
||||
MOVW y+4(FP), AX // want `invalid MOVW of y\+4\(FP\); \*byte is 4-byte value`
|
||||
MOVL x+0(FP), AX
|
||||
MOVL y+4(FP), AX
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); \*byte is 4-byte value`
|
||||
MOVQ y+4(FP), AX // want `invalid MOVQ of y\+4\(FP\); \*byte is 4-byte value`
|
||||
MOVQ x+4(FP), AX // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
TESTB x+0(FP), AX // want `invalid TESTB of x\+0\(FP\); \*byte is 4-byte value`
|
||||
TESTB y+4(FP), BX // want `invalid TESTB of y\+4\(FP\); \*byte is 4-byte value`
|
||||
TESTW x+0(FP), AX // want `invalid TESTW of x\+0\(FP\); \*byte is 4-byte value`
|
||||
TESTW y+4(FP), AX // want `invalid TESTW of y\+4\(FP\); \*byte is 4-byte value`
|
||||
TESTL x+0(FP), AX
|
||||
TESTL y+4(FP), AX
|
||||
TESTQ x+0(FP), AX // want `invalid TESTQ of x\+0\(FP\); \*byte is 4-byte value`
|
||||
TESTQ y+4(FP), AX // want `invalid TESTQ of y\+4\(FP\); \*byte is 4-byte value`
|
||||
TESTQ x+4(FP), AX // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
TESTQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
MOVW c+8(FP), AX // want `invalid MOVW of c\+8\(FP\); chan int is 4-byte value`
|
||||
MOVW m+12(FP), AX // want `invalid MOVW of m\+12\(FP\); map\[int\]int is 4-byte value`
|
||||
MOVW f+16(FP), AX // want `invalid MOVW of f\+16\(FP\); func\(\) is 4-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·argstring(SB),0,$16 // want `wrong argument size 0; expected \$\.\.\.-16`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); string base is 4-byte value`
|
||||
MOVL x+0(FP), AX
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); string base is 4-byte value`
|
||||
MOVW x_base+0(FP), AX // want `invalid MOVW of x_base\+0\(FP\); string base is 4-byte value`
|
||||
MOVL x_base+0(FP), AX
|
||||
MOVQ x_base+0(FP), AX // want `invalid MOVQ of x_base\+0\(FP\); string base is 4-byte value`
|
||||
MOVW x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVL x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVQ x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVW x_len+4(FP), AX // want `invalid MOVW of x_len\+4\(FP\); string len is 4-byte value`
|
||||
MOVL x_len+4(FP), AX
|
||||
MOVQ x_len+4(FP), AX // want `invalid MOVQ of x_len\+4\(FP\); string len is 4-byte value`
|
||||
MOVQ y+0(FP), AX // want `invalid offset y\+0\(FP\); expected y\+8\(FP\)`
|
||||
MOVQ y_len+4(FP), AX // want `invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argslice(SB),0,$24 // want `wrong argument size 0; expected \$\.\.\.-24`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); slice base is 4-byte value`
|
||||
MOVL x+0(FP), AX
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); slice base is 4-byte value`
|
||||
MOVW x_base+0(FP), AX // want `invalid MOVW of x_base\+0\(FP\); slice base is 4-byte value`
|
||||
MOVL x_base+0(FP), AX
|
||||
MOVQ x_base+0(FP), AX // want `invalid MOVQ of x_base\+0\(FP\); slice base is 4-byte value`
|
||||
MOVW x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVL x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVQ x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVW x_len+4(FP), AX // want `invalid MOVW of x_len\+4\(FP\); slice len is 4-byte value`
|
||||
MOVL x_len+4(FP), AX
|
||||
MOVQ x_len+4(FP), AX // want `invalid MOVQ of x_len\+4\(FP\); slice len is 4-byte value`
|
||||
MOVW x_cap+0(FP), AX // want `invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)`
|
||||
MOVL x_cap+0(FP), AX // want `invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)`
|
||||
MOVQ x_cap+0(FP), AX // want `invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)`
|
||||
MOVW x_cap+8(FP), AX // want `invalid MOVW of x_cap\+8\(FP\); slice cap is 4-byte value`
|
||||
MOVL x_cap+8(FP), AX
|
||||
MOVQ x_cap+8(FP), AX // want `invalid MOVQ of x_cap\+8\(FP\); slice cap is 4-byte value`
|
||||
MOVQ y+0(FP), AX // want `invalid offset y\+0\(FP\); expected y\+12\(FP\)`
|
||||
MOVQ y_len+4(FP), AX // want `invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)`
|
||||
MOVQ y_cap+8(FP), AX // want `invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argiface(SB),0,$0-16
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); interface type is 4-byte value`
|
||||
MOVL x+0(FP), AX
|
||||
MOVQ x+0(FP), AX // want `invalid MOVQ of x\+0\(FP\); interface type is 4-byte value`
|
||||
MOVW x_type+0(FP), AX // want `invalid MOVW of x_type\+0\(FP\); interface type is 4-byte value`
|
||||
MOVL x_type+0(FP), AX
|
||||
MOVQ x_type+0(FP), AX // want `invalid MOVQ of x_type\+0\(FP\); interface type is 4-byte value`
|
||||
MOVQ x_itable+0(FP), AX // want `unknown variable x_itable; offset 0 is x_type\+0\(FP\)`
|
||||
MOVQ x_itable+1(FP), AX // want `unknown variable x_itable; offset 1 is x_type\+0\(FP\)`
|
||||
MOVW x_data+0(FP), AX // want `invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)`
|
||||
MOVL x_data+0(FP), AX // want `invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)`
|
||||
MOVQ x_data+0(FP), AX // want `invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)`
|
||||
MOVW x_data+4(FP), AX // want `invalid MOVW of x_data\+4\(FP\); interface data is 4-byte value`
|
||||
MOVL x_data+4(FP), AX
|
||||
MOVQ x_data+4(FP), AX // want `invalid MOVQ of x_data\+4\(FP\); interface data is 4-byte value`
|
||||
MOVW y+8(FP), AX // want `invalid MOVW of y\+8\(FP\); interface itable is 4-byte value`
|
||||
MOVL y+8(FP), AX
|
||||
MOVQ y+8(FP), AX // want `invalid MOVQ of y\+8\(FP\); interface itable is 4-byte value`
|
||||
MOVW y_itable+8(FP), AX // want `invalid MOVW of y_itable\+8\(FP\); interface itable is 4-byte value`
|
||||
MOVL y_itable+8(FP), AX
|
||||
MOVQ y_itable+8(FP), AX // want `invalid MOVQ of y_itable\+8\(FP\); interface itable is 4-byte value`
|
||||
MOVQ y_type+8(FP), AX // want `unknown variable y_type; offset 8 is y_itable\+8\(FP\)`
|
||||
MOVW y_data+8(FP), AX // want `invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)`
|
||||
MOVL y_data+8(FP), AX // want `invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)`
|
||||
MOVQ y_data+8(FP), AX // want `invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)`
|
||||
MOVW y_data+12(FP), AX // want `invalid MOVW of y_data\+12\(FP\); interface data is 4-byte value`
|
||||
MOVL y_data+12(FP), AX
|
||||
MOVQ y_data+12(FP), AX // want `invalid MOVQ of y_data\+12\(FP\); interface data is 4-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·returnint(SB),0,$0-4
|
||||
MOVB AX, ret+0(FP) // want `invalid MOVB of ret\+0\(FP\); int is 4-byte value`
|
||||
MOVW AX, ret+0(FP) // want `invalid MOVW of ret\+0\(FP\); int is 4-byte value`
|
||||
MOVL AX, ret+0(FP)
|
||||
MOVQ AX, ret+0(FP) // want `invalid MOVQ of ret\+0\(FP\); int is 4-byte value`
|
||||
MOVQ AX, ret+1(FP) // want `invalid offset ret\+1\(FP\); expected ret\+0\(FP\)`
|
||||
MOVQ AX, r+0(FP) // want `unknown variable r; offset 0 is ret\+0\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnbyte(SB),0,$0-5
|
||||
MOVL x+0(FP), AX
|
||||
MOVB AX, ret+4(FP)
|
||||
MOVW AX, ret+4(FP) // want `invalid MOVW of ret\+4\(FP\); byte is 1-byte value`
|
||||
MOVL AX, ret+4(FP) // want `invalid MOVL of ret\+4\(FP\); byte is 1-byte value`
|
||||
MOVQ AX, ret+4(FP) // want `invalid MOVQ of ret\+4\(FP\); byte is 1-byte value`
|
||||
MOVB AX, ret+3(FP) // want `invalid offset ret\+3\(FP\); expected ret\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnnamed(SB),0,$0-21
|
||||
MOVB x+0(FP), AX
|
||||
MOVL AX, r1+4(FP)
|
||||
MOVW AX, r2+8(FP)
|
||||
MOVL AX, r3+12(FP)
|
||||
MOVL AX, r3_base+12(FP)
|
||||
MOVL AX, r3_len+16(FP)
|
||||
MOVB AX, r4+20(FP)
|
||||
MOVQ AX, r1+4(FP) // want `invalid MOVQ of r1\+4\(FP\); int is 4-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·returnintmissing(SB),0,$0-4
|
||||
RET // want `RET without writing to 4-byte ret\+0\(FP\)`
|
||||
191
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm3.s
generated
vendored
Normal file
191
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm3.s
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
// Copyright 2013 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 arm
|
||||
|
||||
TEXT ·arg1(SB),0,$0-2
|
||||
MOVB x+0(FP), AX
|
||||
MOVB y+1(FP), BX
|
||||
MOVH x+0(FP), AX // want `\[arm\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVH y+1(FP), AX // want `invalid MOVH of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVW y+1(FP), AX // want `invalid MOVW of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVB x+1(FP), AX // want `invalid offset x\+1\(FP\); expected x\+0\(FP\)`
|
||||
MOVB y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+1\(FP\)`
|
||||
MOVB 8(R13), AX // want `8\(R13\) should be x\+0\(FP\)`
|
||||
MOVB 9(R13), AX // want `9\(R13\) should be y\+1\(FP\)`
|
||||
MOVB 10(R13), AX // want `use of 10\(R13\) points beyond argument frame`
|
||||
RET
|
||||
|
||||
TEXT ·arg2(SB),0,$0-4
|
||||
MOVB x+0(FP), AX // want `arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVB y+2(FP), AX // want `invalid MOVB of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVH x+0(FP), AX
|
||||
MOVH y+2(FP), BX
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVW y+2(FP), AX // want `invalid MOVW of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVH x+2(FP), AX // want `invalid offset x\+2\(FP\); expected x\+0\(FP\)`
|
||||
MOVH y+0(FP), AX // want `invalid offset y\+0\(FP\); expected y\+2\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \$\.\.\.-8`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVB y+4(FP), BX // want `invalid MOVB of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVH x+0(FP), AX // want `invalid MOVH of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVH y+4(FP), AX // want `invalid MOVH of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVW x+0(FP), AX
|
||||
MOVW y+4(FP), AX
|
||||
MOVW x+4(FP), AX // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVW y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-16`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVB y+8(FP), BX // want `invalid MOVB of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVH x+0(FP), AX // want `invalid MOVH of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVH y+8(FP), AX // want `invalid MOVH of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVW x+0(FP), AX // want `invalid MOVW of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)`
|
||||
MOVW x_lo+0(FP), AX
|
||||
MOVW x_hi+4(FP), AX
|
||||
MOVW y+8(FP), AX // want `invalid MOVW of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)`
|
||||
MOVW y_lo+8(FP), AX
|
||||
MOVW y_hi+12(FP), AX
|
||||
MOVQ x+0(FP), AX
|
||||
MOVQ y+8(FP), AX
|
||||
MOVQ x+8(FP), AX // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \$\.\.\.-8`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); int is 4-byte value`
|
||||
MOVB y+4(FP), BX // want `invalid MOVB of y\+4\(FP\); uint is 4-byte value`
|
||||
MOVH x+0(FP), AX // want `invalid MOVH of x\+0\(FP\); int is 4-byte value`
|
||||
MOVH y+4(FP), AX // want `invalid MOVH of y\+4\(FP\); uint is 4-byte value`
|
||||
MOVW x+0(FP), AX
|
||||
MOVW y+4(FP), AX
|
||||
MOVQ x+4(FP), AX // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-20`
|
||||
MOVB x+0(FP), AX // want `invalid MOVB of x\+0\(FP\); \*byte is 4-byte value`
|
||||
MOVB y+4(FP), BX // want `invalid MOVB of y\+4\(FP\); \*byte is 4-byte value`
|
||||
MOVH x+0(FP), AX // want `invalid MOVH of x\+0\(FP\); \*byte is 4-byte value`
|
||||
MOVH y+4(FP), AX // want `invalid MOVH of y\+4\(FP\); \*byte is 4-byte value`
|
||||
MOVW x+0(FP), AX
|
||||
MOVW y+4(FP), AX
|
||||
MOVQ x+4(FP), AX // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVQ y+2(FP), AX // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
MOVH c+8(FP), AX // want `invalid MOVH of c\+8\(FP\); chan int is 4-byte value`
|
||||
MOVH m+12(FP), AX // want `invalid MOVH of m\+12\(FP\); map\[int\]int is 4-byte value`
|
||||
MOVH f+16(FP), AX // want `invalid MOVH of f\+16\(FP\); func\(\) is 4-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·argstring(SB),0,$16 // want `wrong argument size 0; expected \$\.\.\.-16`
|
||||
MOVH x+0(FP), AX // want `invalid MOVH of x\+0\(FP\); string base is 4-byte value`
|
||||
MOVW x+0(FP), AX
|
||||
MOVH x_base+0(FP), AX // want `invalid MOVH of x_base\+0\(FP\); string base is 4-byte value`
|
||||
MOVW x_base+0(FP), AX
|
||||
MOVH x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVW x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVQ x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVH x_len+4(FP), AX // want `invalid MOVH of x_len\+4\(FP\); string len is 4-byte value`
|
||||
MOVW x_len+4(FP), AX
|
||||
MOVQ y+0(FP), AX // want `invalid offset y\+0\(FP\); expected y\+8\(FP\)`
|
||||
MOVQ y_len+4(FP), AX // want `invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argslice(SB),0,$24 // want `wrong argument size 0; expected \$\.\.\.-24`
|
||||
MOVH x+0(FP), AX // want `invalid MOVH of x\+0\(FP\); slice base is 4-byte value`
|
||||
MOVW x+0(FP), AX
|
||||
MOVH x_base+0(FP), AX // want `invalid MOVH of x_base\+0\(FP\); slice base is 4-byte value`
|
||||
MOVW x_base+0(FP), AX
|
||||
MOVH x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVW x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVQ x_len+0(FP), AX // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVH x_len+4(FP), AX // want `invalid MOVH of x_len\+4\(FP\); slice len is 4-byte value`
|
||||
MOVW x_len+4(FP), AX
|
||||
MOVH x_cap+0(FP), AX // want `invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)`
|
||||
MOVW x_cap+0(FP), AX // want `invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)`
|
||||
MOVQ x_cap+0(FP), AX // want `invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)`
|
||||
MOVH x_cap+8(FP), AX // want `invalid MOVH of x_cap\+8\(FP\); slice cap is 4-byte value`
|
||||
MOVW x_cap+8(FP), AX
|
||||
MOVQ y+0(FP), AX // want `invalid offset y\+0\(FP\); expected y\+12\(FP\)`
|
||||
MOVQ y_len+4(FP), AX // want `invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)`
|
||||
MOVQ y_cap+8(FP), AX // want `invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argiface(SB),0,$0-16
|
||||
MOVH x+0(FP), AX // want `invalid MOVH of x\+0\(FP\); interface type is 4-byte value`
|
||||
MOVW x+0(FP), AX
|
||||
MOVH x_type+0(FP), AX // want `invalid MOVH of x_type\+0\(FP\); interface type is 4-byte value`
|
||||
MOVW x_type+0(FP), AX
|
||||
MOVQ x_itable+0(FP), AX // want `unknown variable x_itable; offset 0 is x_type\+0\(FP\)`
|
||||
MOVQ x_itable+1(FP), AX // want `unknown variable x_itable; offset 1 is x_type\+0\(FP\)`
|
||||
MOVH x_data+0(FP), AX // want `invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)`
|
||||
MOVW x_data+0(FP), AX // want `invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)`
|
||||
MOVQ x_data+0(FP), AX // want `invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)`
|
||||
MOVH x_data+4(FP), AX // want `invalid MOVH of x_data\+4\(FP\); interface data is 4-byte value`
|
||||
MOVW x_data+4(FP), AX
|
||||
MOVH y+8(FP), AX // want `invalid MOVH of y\+8\(FP\); interface itable is 4-byte value`
|
||||
MOVW y+8(FP), AX
|
||||
MOVH y_itable+8(FP), AX // want `invalid MOVH of y_itable\+8\(FP\); interface itable is 4-byte value`
|
||||
MOVW y_itable+8(FP), AX
|
||||
MOVQ y_type+8(FP), AX // want `unknown variable y_type; offset 8 is y_itable\+8\(FP\)`
|
||||
MOVH y_data+8(FP), AX // want `invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)`
|
||||
MOVW y_data+8(FP), AX // want `invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)`
|
||||
MOVQ y_data+8(FP), AX // want `invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)`
|
||||
MOVH y_data+12(FP), AX // want `invalid MOVH of y_data\+12\(FP\); interface data is 4-byte value`
|
||||
MOVW y_data+12(FP), AX
|
||||
RET
|
||||
|
||||
TEXT ·returnint(SB),0,$0-4
|
||||
MOVB AX, ret+0(FP) // want `invalid MOVB of ret\+0\(FP\); int is 4-byte value`
|
||||
MOVH AX, ret+0(FP) // want `invalid MOVH of ret\+0\(FP\); int is 4-byte value`
|
||||
MOVW AX, ret+0(FP)
|
||||
MOVQ AX, ret+1(FP) // want `invalid offset ret\+1\(FP\); expected ret\+0\(FP\)`
|
||||
MOVQ AX, r+0(FP) // want `unknown variable r; offset 0 is ret\+0\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnbyte(SB),0,$0-5
|
||||
MOVW x+0(FP), AX
|
||||
MOVB AX, ret+4(FP)
|
||||
MOVH AX, ret+4(FP) // want `invalid MOVH of ret\+4\(FP\); byte is 1-byte value`
|
||||
MOVW AX, ret+4(FP) // want `invalid MOVW of ret\+4\(FP\); byte is 1-byte value`
|
||||
MOVB AX, ret+3(FP) // want `invalid offset ret\+3\(FP\); expected ret\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnnamed(SB),0,$0-21
|
||||
MOVB x+0(FP), AX
|
||||
MOVW AX, r1+4(FP)
|
||||
MOVH AX, r2+8(FP)
|
||||
MOVW AX, r3+12(FP)
|
||||
MOVW AX, r3_base+12(FP)
|
||||
MOVW AX, r3_len+16(FP)
|
||||
MOVB AX, r4+20(FP)
|
||||
MOVB AX, r1+4(FP) // want `invalid MOVB of r1\+4\(FP\); int is 4-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·returnintmissing(SB),0,$0-4
|
||||
RET // want `RET without writing to 4-byte ret\+0\(FP\)`
|
||||
|
||||
TEXT ·leaf(SB),0,$-4-12
|
||||
MOVW x+0(FP), AX
|
||||
MOVW y+4(FP), AX
|
||||
MOVW AX, ret+8(FP)
|
||||
RET
|
||||
|
||||
TEXT ·noframe1(SB),0,$0-4
|
||||
MOVW 0(R13), AX // Okay; our saved LR
|
||||
MOVW 4(R13), AX // Okay; caller's saved LR
|
||||
MOVW x+8(R13), AX // Okay; x argument
|
||||
MOVW 12(R13), AX // want `use of 12\(R13\) points beyond argument frame`
|
||||
RET
|
||||
|
||||
TEXT ·noframe2(SB),NOFRAME,$0-4
|
||||
MOVW 0(R13), AX // Okay; caller's saved LR
|
||||
MOVW x+4(R13), AX // Okay; x argument
|
||||
MOVW 8(R13), AX // want `use of 8\(R13\) points beyond argument frame`
|
||||
MOVW 12(R13), AX // want `use of 12\(R13\) points beyond argument frame`
|
||||
RET
|
||||
25
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm4.s
generated
vendored
Normal file
25
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm4.s
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2013 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 amd64
|
||||
|
||||
// Test cases for symbolic NOSPLIT etc. on TEXT symbols.
|
||||
|
||||
TEXT ·noprof(SB),NOPROF,$0-8
|
||||
RET
|
||||
|
||||
TEXT ·dupok(SB),DUPOK,$0-8
|
||||
RET
|
||||
|
||||
TEXT ·nosplit(SB),NOSPLIT,$0
|
||||
RET
|
||||
|
||||
TEXT ·rodata(SB),RODATA,$0-8
|
||||
RET
|
||||
|
||||
TEXT ·noptr(SB),NOPTR|NOSPLIT,$0
|
||||
RET
|
||||
|
||||
TEXT ·wrapper(SB),WRAPPER,$0-8
|
||||
RET
|
||||
192
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm5.s
generated
vendored
Normal file
192
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm5.s
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
// Copyright 2016 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 mips64
|
||||
|
||||
TEXT ·arg1(SB),0,$0-2
|
||||
MOVB x+0(FP), R1
|
||||
MOVBU y+1(FP), R2
|
||||
MOVH x+0(FP), R1 // want `\[mips64\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVHU y+1(FP), R1 // want `invalid MOVHU of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVWU y+1(FP), R1 // want `invalid MOVWU of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVV x+0(FP), R1 // want `invalid MOVV of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVV y+1(FP), R1 // want `invalid MOVV of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVB x+1(FP), R1 // want `invalid offset x\+1\(FP\); expected x\+0\(FP\)`
|
||||
MOVBU y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+1\(FP\)`
|
||||
MOVB 16(R29), R1 // want `16\(R29\) should be x\+0\(FP\)`
|
||||
MOVB 17(R29), R1 // want `17\(R29\) should be y\+1\(FP\)`
|
||||
MOVB 18(R29), R1 // want `use of 18\(R29\) points beyond argument frame`
|
||||
RET
|
||||
|
||||
TEXT ·arg2(SB),0,$0-4
|
||||
MOVBU x+0(FP), R1 // want `arg2: invalid MOVBU of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVB y+2(FP), R1 // want `invalid MOVB of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVHU x+0(FP), R1
|
||||
MOVH y+2(FP), R2
|
||||
MOVWU x+0(FP), R1 // want `invalid MOVWU of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVW y+2(FP), R1 // want `invalid MOVW of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVV x+0(FP), R1 // want `invalid MOVV of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVV y+2(FP), R1 // want `invalid MOVV of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVHU x+2(FP), R1 // want `invalid offset x\+2\(FP\); expected x\+0\(FP\)`
|
||||
MOVH y+0(FP), R1 // want `invalid offset y\+0\(FP\); expected y\+2\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \$\.\.\.-8`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVB y+4(FP), R2 // want `invalid MOVB of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVH y+4(FP), R1 // want `invalid MOVH of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVW x+0(FP), R1
|
||||
MOVW y+4(FP), R1
|
||||
MOVV x+0(FP), R1 // want `invalid MOVV of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVV y+4(FP), R1 // want `invalid MOVV of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVW x+4(FP), R1 // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVW y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-16`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVB y+8(FP), R2 // want `invalid MOVB of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVH y+8(FP), R1 // want `invalid MOVH of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVW y+8(FP), R1 // want `invalid MOVW of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVV x+0(FP), R1
|
||||
MOVV y+8(FP), R1
|
||||
MOVV x+8(FP), R1 // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVV y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \$\.\.\.-16`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); int is 8-byte value`
|
||||
MOVB y+8(FP), R2 // want `invalid MOVB of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); int is 8-byte value`
|
||||
MOVH y+8(FP), R1 // want `invalid MOVH of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); int is 8-byte value`
|
||||
MOVW y+8(FP), R1 // want `invalid MOVW of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVV x+0(FP), R1
|
||||
MOVV y+8(FP), R1
|
||||
MOVV x+8(FP), R1 // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVV y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-40`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVB y+8(FP), R2 // want `invalid MOVB of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVH y+8(FP), R1 // want `invalid MOVH of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVW y+8(FP), R1 // want `invalid MOVW of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVV x+0(FP), R1
|
||||
MOVV y+8(FP), R1
|
||||
MOVV x+8(FP), R1 // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVV y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
MOVW c+16(FP), R1 // want `invalid MOVW of c\+16\(FP\); chan int is 8-byte value`
|
||||
MOVW m+24(FP), R1 // want `invalid MOVW of m\+24\(FP\); map\[int\]int is 8-byte value`
|
||||
MOVW f+32(FP), R1 // want `invalid MOVW of f\+32\(FP\); func\(\) is 8-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·argstring(SB),0,$32 // want `wrong argument size 0; expected \$\.\.\.-32`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); string base is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); string base is 8-byte value`
|
||||
MOVV x+0(FP), R1
|
||||
MOVH x_base+0(FP), R1 // want `invalid MOVH of x_base\+0\(FP\); string base is 8-byte value`
|
||||
MOVW x_base+0(FP), R1 // want `invalid MOVW of x_base\+0\(FP\); string base is 8-byte value`
|
||||
MOVV x_base+0(FP), R1
|
||||
MOVH x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVW x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVV x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVH x_len+8(FP), R1 // want `invalid MOVH of x_len\+8\(FP\); string len is 8-byte value`
|
||||
MOVW x_len+8(FP), R1 // want `invalid MOVW of x_len\+8\(FP\); string len is 8-byte value`
|
||||
MOVV x_len+8(FP), R1
|
||||
MOVV y+0(FP), R1 // want `invalid offset y\+0\(FP\); expected y\+16\(FP\)`
|
||||
MOVV y_len+8(FP), R1 // want `invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argslice(SB),0,$48 // want `wrong argument size 0; expected \$\.\.\.-48`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); slice base is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); slice base is 8-byte value`
|
||||
MOVV x+0(FP), R1
|
||||
MOVH x_base+0(FP), R1 // want `invalid MOVH of x_base\+0\(FP\); slice base is 8-byte value`
|
||||
MOVW x_base+0(FP), R1 // want `invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value`
|
||||
MOVV x_base+0(FP), R1
|
||||
MOVH x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVW x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVV x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVH x_len+8(FP), R1 // want `invalid MOVH of x_len\+8\(FP\); slice len is 8-byte value`
|
||||
MOVW x_len+8(FP), R1 // want `invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value`
|
||||
MOVV x_len+8(FP), R1
|
||||
MOVH x_cap+0(FP), R1 // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVW x_cap+0(FP), R1 // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVV x_cap+0(FP), R1 // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVH x_cap+16(FP), R1 // want `invalid MOVH of x_cap\+16\(FP\); slice cap is 8-byte value`
|
||||
MOVW x_cap+16(FP), R1 // want `invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value`
|
||||
MOVV x_cap+16(FP), R1
|
||||
MOVV y+0(FP), R1 // want `invalid offset y\+0\(FP\); expected y\+24\(FP\)`
|
||||
MOVV y_len+8(FP), R1 // want `invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)`
|
||||
MOVV y_cap+16(FP), R1 // want `invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argiface(SB),0,$0-32
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); interface type is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); interface type is 8-byte value`
|
||||
MOVV x+0(FP), R1
|
||||
MOVH x_type+0(FP), R1 // want `invalid MOVH of x_type\+0\(FP\); interface type is 8-byte value`
|
||||
MOVW x_type+0(FP), R1 // want `invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value`
|
||||
MOVV x_type+0(FP), R1
|
||||
MOVV x_itable+0(FP), R1 // want `unknown variable x_itable; offset 0 is x_type\+0\(FP\)`
|
||||
MOVV x_itable+1(FP), R1 // want `unknown variable x_itable; offset 1 is x_type\+0\(FP\)`
|
||||
MOVH x_data+0(FP), R1 // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVW x_data+0(FP), R1 // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVV x_data+0(FP), R1 // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVH x_data+8(FP), R1 // want `invalid MOVH of x_data\+8\(FP\); interface data is 8-byte value`
|
||||
MOVW x_data+8(FP), R1 // want `invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value`
|
||||
MOVV x_data+8(FP), R1
|
||||
MOVH y+16(FP), R1 // want `invalid MOVH of y\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVW y+16(FP), R1 // want `invalid MOVW of y\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVV y+16(FP), R1
|
||||
MOVH y_itable+16(FP), R1 // want `invalid MOVH of y_itable\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVW y_itable+16(FP), R1 // want `invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVV y_itable+16(FP), R1
|
||||
MOVV y_type+16(FP), R1 // want `unknown variable y_type; offset 16 is y_itable\+16\(FP\)`
|
||||
MOVH y_data+16(FP), R1 // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVW y_data+16(FP), R1 // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVV y_data+16(FP), R1 // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVH y_data+24(FP), R1 // want `invalid MOVH of y_data\+24\(FP\); interface data is 8-byte value`
|
||||
MOVW y_data+24(FP), R1 // want `invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value`
|
||||
MOVV y_data+24(FP), R1
|
||||
RET
|
||||
|
||||
TEXT ·returnint(SB),0,$0-8
|
||||
MOVB R1, ret+0(FP) // want `invalid MOVB of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVH R1, ret+0(FP) // want `invalid MOVH of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVW R1, ret+0(FP) // want `invalid MOVW of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVV R1, ret+0(FP)
|
||||
MOVV R1, ret+1(FP) // want `invalid offset ret\+1\(FP\); expected ret\+0\(FP\)`
|
||||
MOVV R1, r+0(FP) // want `unknown variable r; offset 0 is ret\+0\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnbyte(SB),0,$0-9
|
||||
MOVV x+0(FP), R1
|
||||
MOVB R1, ret+8(FP)
|
||||
MOVH R1, ret+8(FP) // want `invalid MOVH of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVW R1, ret+8(FP) // want `invalid MOVW of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVV R1, ret+8(FP) // want `invalid MOVV of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVB R1, ret+7(FP) // want `invalid offset ret\+7\(FP\); expected ret\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnnamed(SB),0,$0-41
|
||||
MOVB x+0(FP), R1
|
||||
MOVV R1, r1+8(FP)
|
||||
MOVH R1, r2+16(FP)
|
||||
MOVV R1, r3+24(FP)
|
||||
MOVV R1, r3_base+24(FP)
|
||||
MOVV R1, r3_len+32(FP)
|
||||
MOVB R1, r4+40(FP)
|
||||
MOVW R1, r1+8(FP) // want `invalid MOVW of r1\+8\(FP\); int is 8-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·returnintmissing(SB),0,$0-8
|
||||
RET // want `RET without writing to 8-byte ret\+0\(FP\)`
|
||||
192
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm6.s
generated
vendored
Normal file
192
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm6.s
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
// Copyright 2016 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 s390x
|
||||
|
||||
TEXT ·arg1(SB),0,$0-2
|
||||
MOVB x+0(FP), R1
|
||||
MOVBZ y+1(FP), R2
|
||||
MOVH x+0(FP), R1 // want `\[s390x\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVHZ y+1(FP), R1 // want `invalid MOVHZ of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVWZ y+1(FP), R1 // want `invalid MOVWZ of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVD x+0(FP), R1 // want `invalid MOVD of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVD y+1(FP), R1 // want `invalid MOVD of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVB x+1(FP), R1 // want `invalid offset x\+1\(FP\); expected x\+0\(FP\)`
|
||||
MOVBZ y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+1\(FP\)`
|
||||
MOVB 16(R15), R1 // want `16\(R15\) should be x\+0\(FP\)`
|
||||
MOVB 17(R15), R1 // want `17\(R15\) should be y\+1\(FP\)`
|
||||
MOVB 18(R15), R1 // want `use of 18\(R15\) points beyond argument frame`
|
||||
RET
|
||||
|
||||
TEXT ·arg2(SB),0,$0-4
|
||||
MOVBZ x+0(FP), R1 // want `arg2: invalid MOVBZ of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVB y+2(FP), R1 // want `invalid MOVB of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVHZ x+0(FP), R1
|
||||
MOVH y+2(FP), R2
|
||||
MOVWZ x+0(FP), R1 // want `invalid MOVWZ of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVW y+2(FP), R1 // want `invalid MOVW of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVD x+0(FP), R1 // want `invalid MOVD of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVD y+2(FP), R1 // want `invalid MOVD of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVHZ x+2(FP), R1 // want `invalid offset x\+2\(FP\); expected x\+0\(FP\)`
|
||||
MOVH y+0(FP), R1 // want `invalid offset y\+0\(FP\); expected y\+2\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \$\.\.\.-8`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVB y+4(FP), R2 // want `invalid MOVB of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVH y+4(FP), R1 // want `invalid MOVH of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVW x+0(FP), R1
|
||||
MOVW y+4(FP), R1
|
||||
MOVD x+0(FP), R1 // want `invalid MOVD of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVD y+4(FP), R1 // want `invalid MOVD of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVW x+4(FP), R1 // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVW y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-16`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVB y+8(FP), R2 // want `invalid MOVB of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVH y+8(FP), R1 // want `invalid MOVH of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVW y+8(FP), R1 // want `invalid MOVW of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVD x+0(FP), R1
|
||||
MOVD y+8(FP), R1
|
||||
MOVD x+8(FP), R1 // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVD y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \$\.\.\.-16`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); int is 8-byte value`
|
||||
MOVB y+8(FP), R2 // want `invalid MOVB of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); int is 8-byte value`
|
||||
MOVH y+8(FP), R1 // want `invalid MOVH of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); int is 8-byte value`
|
||||
MOVW y+8(FP), R1 // want `invalid MOVW of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVD x+0(FP), R1
|
||||
MOVD y+8(FP), R1
|
||||
MOVD x+8(FP), R1 // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVD y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-40`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVB y+8(FP), R2 // want `invalid MOVB of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVH y+8(FP), R1 // want `invalid MOVH of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVW y+8(FP), R1 // want `invalid MOVW of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVD x+0(FP), R1
|
||||
MOVD y+8(FP), R1
|
||||
MOVD x+8(FP), R1 // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVD y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
MOVW c+16(FP), R1 // want `invalid MOVW of c\+16\(FP\); chan int is 8-byte value`
|
||||
MOVW m+24(FP), R1 // want `invalid MOVW of m\+24\(FP\); map\[int\]int is 8-byte value`
|
||||
MOVW f+32(FP), R1 // want `invalid MOVW of f\+32\(FP\); func\(\) is 8-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·argstring(SB),0,$32 // want `wrong argument size 0; expected \$\.\.\.-32`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); string base is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); string base is 8-byte value`
|
||||
MOVD x+0(FP), R1
|
||||
MOVH x_base+0(FP), R1 // want `invalid MOVH of x_base\+0\(FP\); string base is 8-byte value`
|
||||
MOVW x_base+0(FP), R1 // want `invalid MOVW of x_base\+0\(FP\); string base is 8-byte value`
|
||||
MOVD x_base+0(FP), R1
|
||||
MOVH x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVW x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVD x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVH x_len+8(FP), R1 // want `invalid MOVH of x_len\+8\(FP\); string len is 8-byte value`
|
||||
MOVW x_len+8(FP), R1 // want `invalid MOVW of x_len\+8\(FP\); string len is 8-byte value`
|
||||
MOVD x_len+8(FP), R1
|
||||
MOVD y+0(FP), R1 // want `invalid offset y\+0\(FP\); expected y\+16\(FP\)`
|
||||
MOVD y_len+8(FP), R1 // want `invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argslice(SB),0,$48 // want `wrong argument size 0; expected \$\.\.\.-48`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); slice base is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); slice base is 8-byte value`
|
||||
MOVD x+0(FP), R1
|
||||
MOVH x_base+0(FP), R1 // want `invalid MOVH of x_base\+0\(FP\); slice base is 8-byte value`
|
||||
MOVW x_base+0(FP), R1 // want `invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value`
|
||||
MOVD x_base+0(FP), R1
|
||||
MOVH x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVW x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVD x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVH x_len+8(FP), R1 // want `invalid MOVH of x_len\+8\(FP\); slice len is 8-byte value`
|
||||
MOVW x_len+8(FP), R1 // want `invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value`
|
||||
MOVD x_len+8(FP), R1
|
||||
MOVH x_cap+0(FP), R1 // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVW x_cap+0(FP), R1 // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVD x_cap+0(FP), R1 // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVH x_cap+16(FP), R1 // want `invalid MOVH of x_cap\+16\(FP\); slice cap is 8-byte value`
|
||||
MOVW x_cap+16(FP), R1 // want `invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value`
|
||||
MOVD x_cap+16(FP), R1
|
||||
MOVD y+0(FP), R1 // want `invalid offset y\+0\(FP\); expected y\+24\(FP\)`
|
||||
MOVD y_len+8(FP), R1 // want `invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)`
|
||||
MOVD y_cap+16(FP), R1 // want `invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argiface(SB),0,$0-32
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); interface type is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); interface type is 8-byte value`
|
||||
MOVD x+0(FP), R1
|
||||
MOVH x_type+0(FP), R1 // want `invalid MOVH of x_type\+0\(FP\); interface type is 8-byte value`
|
||||
MOVW x_type+0(FP), R1 // want `invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value`
|
||||
MOVD x_type+0(FP), R1
|
||||
MOVD x_itable+0(FP), R1 // want `unknown variable x_itable; offset 0 is x_type\+0\(FP\)`
|
||||
MOVD x_itable+1(FP), R1 // want `unknown variable x_itable; offset 1 is x_type\+0\(FP\)`
|
||||
MOVH x_data+0(FP), R1 // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVW x_data+0(FP), R1 // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVD x_data+0(FP), R1 // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVH x_data+8(FP), R1 // want `invalid MOVH of x_data\+8\(FP\); interface data is 8-byte value`
|
||||
MOVW x_data+8(FP), R1 // want `invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value`
|
||||
MOVD x_data+8(FP), R1
|
||||
MOVH y+16(FP), R1 // want `invalid MOVH of y\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVW y+16(FP), R1 // want `invalid MOVW of y\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVD y+16(FP), R1
|
||||
MOVH y_itable+16(FP), R1 // want `invalid MOVH of y_itable\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVW y_itable+16(FP), R1 // want `invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVD y_itable+16(FP), R1
|
||||
MOVD y_type+16(FP), R1 // want `unknown variable y_type; offset 16 is y_itable\+16\(FP\)`
|
||||
MOVH y_data+16(FP), R1 // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVW y_data+16(FP), R1 // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVD y_data+16(FP), R1 // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVH y_data+24(FP), R1 // want `invalid MOVH of y_data\+24\(FP\); interface data is 8-byte value`
|
||||
MOVW y_data+24(FP), R1 // want `invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value`
|
||||
MOVD y_data+24(FP), R1
|
||||
RET
|
||||
|
||||
TEXT ·returnint(SB),0,$0-8
|
||||
MOVB R1, ret+0(FP) // want `invalid MOVB of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVH R1, ret+0(FP) // want `invalid MOVH of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVW R1, ret+0(FP) // want `invalid MOVW of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVD R1, ret+0(FP)
|
||||
MOVD R1, ret+1(FP) // want `invalid offset ret\+1\(FP\); expected ret\+0\(FP\)`
|
||||
MOVD R1, r+0(FP) // want `unknown variable r; offset 0 is ret\+0\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnbyte(SB),0,$0-9
|
||||
MOVD x+0(FP), R1
|
||||
MOVB R1, ret+8(FP)
|
||||
MOVH R1, ret+8(FP) // want `invalid MOVH of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVW R1, ret+8(FP) // want `invalid MOVW of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVD R1, ret+8(FP) // want `invalid MOVD of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVB R1, ret+7(FP) // want `invalid offset ret\+7\(FP\); expected ret\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnnamed(SB),0,$0-41
|
||||
MOVB x+0(FP), R1
|
||||
MOVD R1, r1+8(FP)
|
||||
MOVH R1, r2+16(FP)
|
||||
MOVD R1, r3+24(FP)
|
||||
MOVD R1, r3_base+24(FP)
|
||||
MOVD R1, r3_len+32(FP)
|
||||
MOVB R1, r4+40(FP)
|
||||
MOVW R1, r1+8(FP) // want `invalid MOVW of r1\+8\(FP\); int is 8-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·returnintmissing(SB),0,$0-8
|
||||
RET // want `RET without writing to 8-byte ret\+0\(FP\)`
|
||||
192
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm7.s
generated
vendored
Normal file
192
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm7.s
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
// Copyright 2016 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 ppc64 ppc64le
|
||||
|
||||
TEXT ·arg1(SB),0,$0-2
|
||||
MOVB x+0(FP), R3
|
||||
MOVBZ y+1(FP), R4
|
||||
MOVH x+0(FP), R3 // want `\[(ppc64|ppc64le)\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVHZ y+1(FP), R3 // want `invalid MOVHZ of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVW x+0(FP), R3 // want `invalid MOVW of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVWZ y+1(FP), R3 // want `invalid MOVWZ of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVD x+0(FP), R3 // want `invalid MOVD of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVD y+1(FP), R3 // want `invalid MOVD of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVB x+1(FP), R3 // want `invalid offset x\+1\(FP\); expected x\+0\(FP\)`
|
||||
MOVBZ y+2(FP), R3 // want `invalid offset y\+2\(FP\); expected y\+1\(FP\)`
|
||||
MOVB 16(R1), R3 // want `16\(R1\) should be x\+0\(FP\)`
|
||||
MOVB 17(R1), R3 // want `17\(R1\) should be y\+1\(FP\)`
|
||||
MOVB 18(R1), R3 // want `use of 18\(R1\) points beyond argument frame`
|
||||
RET
|
||||
|
||||
TEXT ·arg2(SB),0,$0-4
|
||||
MOVBZ x+0(FP), R3 // want `arg2: invalid MOVBZ of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVB y+2(FP), R3 // want `invalid MOVB of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVHZ x+0(FP), R3
|
||||
MOVH y+2(FP), R4
|
||||
MOVWZ x+0(FP), R3 // want `invalid MOVWZ of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVW y+2(FP), R3 // want `invalid MOVW of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVD x+0(FP), R3 // want `invalid MOVD of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVD y+2(FP), R3 // want `invalid MOVD of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVHZ x+2(FP), R3 // want `invalid offset x\+2\(FP\); expected x\+0\(FP\)`
|
||||
MOVH y+0(FP), R3 // want `invalid offset y\+0\(FP\); expected y\+2\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \$\.\.\.-8`
|
||||
MOVB x+0(FP), R3 // want `invalid MOVB of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVB y+4(FP), R4 // want `invalid MOVB of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVH x+0(FP), R3 // want `invalid MOVH of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVH y+4(FP), R3 // want `invalid MOVH of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVW x+0(FP), R3
|
||||
MOVW y+4(FP), R3
|
||||
MOVD x+0(FP), R3 // want `invalid MOVD of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVD y+4(FP), R3 // want `invalid MOVD of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVW x+4(FP), R3 // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVW y+2(FP), R3 // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-16`
|
||||
MOVB x+0(FP), R3 // want `invalid MOVB of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVB y+8(FP), R4 // want `invalid MOVB of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVH x+0(FP), R3 // want `invalid MOVH of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVH y+8(FP), R3 // want `invalid MOVH of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVW x+0(FP), R3 // want `invalid MOVW of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVW y+8(FP), R3 // want `invalid MOVW of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVD x+0(FP), R3
|
||||
MOVD y+8(FP), R3
|
||||
MOVD x+8(FP), R3 // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVD y+2(FP), R3 // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \$\.\.\.-16`
|
||||
MOVB x+0(FP), R3 // want `invalid MOVB of x\+0\(FP\); int is 8-byte value`
|
||||
MOVB y+8(FP), R4 // want `invalid MOVB of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVH x+0(FP), R3 // want `invalid MOVH of x\+0\(FP\); int is 8-byte value`
|
||||
MOVH y+8(FP), R3 // want `invalid MOVH of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVW x+0(FP), R3 // want `invalid MOVW of x\+0\(FP\); int is 8-byte value`
|
||||
MOVW y+8(FP), R3 // want `invalid MOVW of y\+8\(FP\); uint is 8-byte value`
|
||||
MOVD x+0(FP), R3
|
||||
MOVD y+8(FP), R3
|
||||
MOVD x+8(FP), R3 // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVD y+2(FP), R3 // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-40`
|
||||
MOVB x+0(FP), R3 // want `invalid MOVB of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVB y+8(FP), R4 // want `invalid MOVB of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVH x+0(FP), R3 // want `invalid MOVH of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVH y+8(FP), R3 // want `invalid MOVH of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVW x+0(FP), R3 // want `invalid MOVW of x\+0\(FP\); \*byte is 8-byte value`
|
||||
MOVW y+8(FP), R3 // want `invalid MOVW of y\+8\(FP\); \*byte is 8-byte value`
|
||||
MOVD x+0(FP), R3
|
||||
MOVD y+8(FP), R3
|
||||
MOVD x+8(FP), R3 // want `invalid offset x\+8\(FP\); expected x\+0\(FP\)`
|
||||
MOVD y+2(FP), R3 // want `invalid offset y\+2\(FP\); expected y\+8\(FP\)`
|
||||
MOVW c+16(FP), R3 // want `invalid MOVW of c\+16\(FP\); chan int is 8-byte value`
|
||||
MOVW m+24(FP), R3 // want `invalid MOVW of m\+24\(FP\); map\[int\]int is 8-byte value`
|
||||
MOVW f+32(FP), R3 // want `invalid MOVW of f\+32\(FP\); func\(\) is 8-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·argstring(SB),0,$32 // want `wrong argument size 0; expected \$\.\.\.-32`
|
||||
MOVH x+0(FP), R3 // want `invalid MOVH of x\+0\(FP\); string base is 8-byte value`
|
||||
MOVW x+0(FP), R3 // want `invalid MOVW of x\+0\(FP\); string base is 8-byte value`
|
||||
MOVD x+0(FP), R3
|
||||
MOVH x_base+0(FP), R3 // want `invalid MOVH of x_base\+0\(FP\); string base is 8-byte value`
|
||||
MOVW x_base+0(FP), R3 // want `invalid MOVW of x_base\+0\(FP\); string base is 8-byte value`
|
||||
MOVD x_base+0(FP), R3
|
||||
MOVH x_len+0(FP), R3 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVW x_len+0(FP), R3 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVD x_len+0(FP), R3 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVH x_len+8(FP), R3 // want `invalid MOVH of x_len\+8\(FP\); string len is 8-byte value`
|
||||
MOVW x_len+8(FP), R3 // want `invalid MOVW of x_len\+8\(FP\); string len is 8-byte value`
|
||||
MOVD x_len+8(FP), R3
|
||||
MOVD y+0(FP), R3 // want `invalid offset y\+0\(FP\); expected y\+16\(FP\)`
|
||||
MOVD y_len+8(FP), R3 // want `invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argslice(SB),0,$48 // want `wrong argument size 0; expected \$\.\.\.-48`
|
||||
MOVH x+0(FP), R3 // want `invalid MOVH of x\+0\(FP\); slice base is 8-byte value`
|
||||
MOVW x+0(FP), R3 // want `invalid MOVW of x\+0\(FP\); slice base is 8-byte value`
|
||||
MOVD x+0(FP), R3
|
||||
MOVH x_base+0(FP), R3 // want `invalid MOVH of x_base\+0\(FP\); slice base is 8-byte value`
|
||||
MOVW x_base+0(FP), R3 // want `invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value`
|
||||
MOVD x_base+0(FP), R3
|
||||
MOVH x_len+0(FP), R3 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVW x_len+0(FP), R3 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVD x_len+0(FP), R3 // want `invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)`
|
||||
MOVH x_len+8(FP), R3 // want `invalid MOVH of x_len\+8\(FP\); slice len is 8-byte value`
|
||||
MOVW x_len+8(FP), R3 // want `invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value`
|
||||
MOVD x_len+8(FP), R3
|
||||
MOVH x_cap+0(FP), R3 // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVW x_cap+0(FP), R3 // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVD x_cap+0(FP), R3 // want `invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)`
|
||||
MOVH x_cap+16(FP), R3 // want `invalid MOVH of x_cap\+16\(FP\); slice cap is 8-byte value`
|
||||
MOVW x_cap+16(FP), R3 // want `invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value`
|
||||
MOVD x_cap+16(FP), R3
|
||||
MOVD y+0(FP), R3 // want `invalid offset y\+0\(FP\); expected y\+24\(FP\)`
|
||||
MOVD y_len+8(FP), R3 // want `invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)`
|
||||
MOVD y_cap+16(FP), R3 // want `invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argiface(SB),0,$0-32
|
||||
MOVH x+0(FP), R3 // want `invalid MOVH of x\+0\(FP\); interface type is 8-byte value`
|
||||
MOVW x+0(FP), R3 // want `invalid MOVW of x\+0\(FP\); interface type is 8-byte value`
|
||||
MOVD x+0(FP), R3
|
||||
MOVH x_type+0(FP), R3 // want `invalid MOVH of x_type\+0\(FP\); interface type is 8-byte value`
|
||||
MOVW x_type+0(FP), R3 // want `invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value`
|
||||
MOVD x_type+0(FP), R3
|
||||
MOVD x_itable+0(FP), R3 // want `unknown variable x_itable; offset 0 is x_type\+0\(FP\)`
|
||||
MOVD x_itable+1(FP), R3 // want `unknown variable x_itable; offset 1 is x_type\+0\(FP\)`
|
||||
MOVH x_data+0(FP), R3 // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVW x_data+0(FP), R3 // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVD x_data+0(FP), R3 // want `invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)`
|
||||
MOVH x_data+8(FP), R3 // want `invalid MOVH of x_data\+8\(FP\); interface data is 8-byte value`
|
||||
MOVW x_data+8(FP), R3 // want `invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value`
|
||||
MOVD x_data+8(FP), R3
|
||||
MOVH y+16(FP), R3 // want `invalid MOVH of y\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVW y+16(FP), R3 // want `invalid MOVW of y\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVD y+16(FP), R3
|
||||
MOVH y_itable+16(FP), R3 // want `invalid MOVH of y_itable\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVW y_itable+16(FP), R3 // want `invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value`
|
||||
MOVD y_itable+16(FP), R3
|
||||
MOVD y_type+16(FP), R3 // want `unknown variable y_type; offset 16 is y_itable\+16\(FP\)`
|
||||
MOVH y_data+16(FP), R3 // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVW y_data+16(FP), R3 // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVD y_data+16(FP), R3 // want `invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)`
|
||||
MOVH y_data+24(FP), R3 // want `invalid MOVH of y_data\+24\(FP\); interface data is 8-byte value`
|
||||
MOVW y_data+24(FP), R3 // want `invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value`
|
||||
MOVD y_data+24(FP), R3
|
||||
RET
|
||||
|
||||
TEXT ·returnint(SB),0,$0-8
|
||||
MOVB R3, ret+0(FP) // want `invalid MOVB of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVH R3, ret+0(FP) // want `invalid MOVH of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVW R3, ret+0(FP) // want `invalid MOVW of ret\+0\(FP\); int is 8-byte value`
|
||||
MOVD R3, ret+0(FP)
|
||||
MOVD R3, ret+1(FP) // want `invalid offset ret\+1\(FP\); expected ret\+0\(FP\)`
|
||||
MOVD R3, r+0(FP) // want `unknown variable r; offset 0 is ret\+0\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnbyte(SB),0,$0-9
|
||||
MOVD x+0(FP), R3
|
||||
MOVB R3, ret+8(FP)
|
||||
MOVH R3, ret+8(FP) // want `invalid MOVH of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVW R3, ret+8(FP) // want `invalid MOVW of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVD R3, ret+8(FP) // want `invalid MOVD of ret\+8\(FP\); byte is 1-byte value`
|
||||
MOVB R3, ret+7(FP) // want `invalid offset ret\+7\(FP\); expected ret\+8\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnnamed(SB),0,$0-41
|
||||
MOVB x+0(FP), R3
|
||||
MOVD R3, r1+8(FP)
|
||||
MOVH R3, r2+16(FP)
|
||||
MOVD R3, r3+24(FP)
|
||||
MOVD R3, r3_base+24(FP)
|
||||
MOVD R3, r3_len+32(FP)
|
||||
MOVB R3, r4+40(FP)
|
||||
MOVW R3, r1+8(FP) // want `invalid MOVW of r1\+8\(FP\); int is 8-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·returnintmissing(SB),0,$0-8
|
||||
RET // want `RET without writing to 8-byte ret\+0\(FP\)`
|
||||
164
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm8.s
generated
vendored
Normal file
164
vendor/golang.org/x/tools/go/analysis/passes/asmdecl/testdata/src/a/asm8.s
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
// Copyright 2016 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 mipsle
|
||||
|
||||
TEXT ·arg1(SB),0,$0-2
|
||||
MOVB x+0(FP), R1
|
||||
MOVBU y+1(FP), R2
|
||||
MOVH x+0(FP), R1 // want `\[mipsle\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVHU y+1(FP), R1 // want `invalid MOVHU of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); int8 is 1-byte value`
|
||||
MOVWU y+1(FP), R1 // want `invalid MOVWU of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVW y+1(FP), R1 // want `invalid MOVW of y\+1\(FP\); uint8 is 1-byte value`
|
||||
MOVB x+1(FP), R1 // want `invalid offset x\+1\(FP\); expected x\+0\(FP\)`
|
||||
MOVBU y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+1\(FP\)`
|
||||
MOVB 8(R29), R1 // want `8\(R29\) should be x\+0\(FP\)`
|
||||
MOVB 9(R29), R1 // want `9\(R29\) should be y\+1\(FP\)`
|
||||
MOVB 10(R29), R1 // want `use of 10\(R29\) points beyond argument frame`
|
||||
RET
|
||||
|
||||
TEXT ·arg2(SB),0,$0-4
|
||||
MOVBU x+0(FP), R1 // want `arg2: invalid MOVBU of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVB y+2(FP), R1 // want `invalid MOVB of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVHU x+0(FP), R1
|
||||
MOVH y+2(FP), R2
|
||||
MOVWU x+0(FP), R1 // want `invalid MOVWU of x\+0\(FP\); int16 is 2-byte value`
|
||||
MOVW y+2(FP), R1 // want `invalid MOVW of y\+2\(FP\); uint16 is 2-byte value`
|
||||
MOVHU x+2(FP), R1 // want `invalid offset x\+2\(FP\); expected x\+0\(FP\)`
|
||||
MOVH y+0(FP), R1 // want `invalid offset y\+0\(FP\); expected y\+2\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg4(SB),0,$0-2 // want `arg4: wrong argument size 2; expected \$\.\.\.-8`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVB y+4(FP), R2 // want `invalid MOVB of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); int32 is 4-byte value`
|
||||
MOVH y+4(FP), R1 // want `invalid MOVH of y\+4\(FP\); uint32 is 4-byte value`
|
||||
MOVW x+0(FP), R1
|
||||
MOVW y+4(FP), R1
|
||||
MOVW x+4(FP), R1 // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVW y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·arg8(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-16`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVB y+8(FP), R2 // want `invalid MOVB of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); int64 is 8-byte value`
|
||||
MOVH y+8(FP), R1 // want `invalid MOVH of y\+8\(FP\); uint64 is 8-byte value`
|
||||
MOVW x+0(FP), R1 // want `invalid MOVW of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)`
|
||||
MOVW x_lo+0(FP), R1
|
||||
MOVW x_hi+4(FP), R1
|
||||
MOVW y+8(FP), R1 // want `invalid MOVW of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)`
|
||||
MOVW y_lo+8(FP), R1
|
||||
MOVW y_hi+12(FP), R1
|
||||
RET
|
||||
|
||||
TEXT ·argint(SB),0,$0-2 // want `wrong argument size 2; expected \$\.\.\.-8`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); int is 4-byte value`
|
||||
MOVB y+4(FP), R2 // want `invalid MOVB of y\+4\(FP\); uint is 4-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); int is 4-byte value`
|
||||
MOVH y+4(FP), R1 // want `invalid MOVH of y\+4\(FP\); uint is 4-byte value`
|
||||
MOVW x+0(FP), R1
|
||||
MOVW y+4(FP), R1
|
||||
MOVW x+4(FP), R1 // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVW y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argptr(SB),7,$0-2 // want `wrong argument size 2; expected \$\.\.\.-20`
|
||||
MOVB x+0(FP), R1 // want `invalid MOVB of x\+0\(FP\); \*byte is 4-byte value`
|
||||
MOVB y+4(FP), R2 // want `invalid MOVB of y\+4\(FP\); \*byte is 4-byte value`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); \*byte is 4-byte value`
|
||||
MOVH y+4(FP), R1 // want `invalid MOVH of y\+4\(FP\); \*byte is 4-byte value`
|
||||
MOVW x+0(FP), R1
|
||||
MOVW y+4(FP), R1
|
||||
MOVW x+4(FP), R1 // want `invalid offset x\+4\(FP\); expected x\+0\(FP\)`
|
||||
MOVW y+2(FP), R1 // want `invalid offset y\+2\(FP\); expected y\+4\(FP\)`
|
||||
MOVH c+8(FP), R1 // want `invalid MOVH of c\+8\(FP\); chan int is 4-byte value`
|
||||
MOVH m+12(FP), R1 // want `invalid MOVH of m\+12\(FP\); map\[int\]int is 4-byte value`
|
||||
MOVH f+16(FP), R1 // want `invalid MOVH of f\+16\(FP\); func\(\) is 4-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·argstring(SB),0,$16 // want `wrong argument size 0; expected \$\.\.\.-16`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); string base is 4-byte value`
|
||||
MOVW x+0(FP), R1
|
||||
MOVH x_base+0(FP), R1 // want `invalid MOVH of x_base\+0\(FP\); string base is 4-byte value`
|
||||
MOVW x_base+0(FP), R1
|
||||
MOVH x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVW x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVH x_len+4(FP), R1 // want `invalid MOVH of x_len\+4\(FP\); string len is 4-byte value`
|
||||
MOVW x_len+4(FP), R1
|
||||
MOVW y+0(FP), R1 // want `invalid offset y\+0\(FP\); expected y\+8\(FP\)`
|
||||
MOVW y_len+4(FP), R1 // want `invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argslice(SB),0,$24 // want `wrong argument size 0; expected \$\.\.\.-24`
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); slice base is 4-byte value`
|
||||
MOVW x+0(FP), R1
|
||||
MOVH x_base+0(FP), R1 // want `invalid MOVH of x_base\+0\(FP\); slice base is 4-byte value`
|
||||
MOVW x_base+0(FP), R1
|
||||
MOVH x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVW x_len+0(FP), R1 // want `invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)`
|
||||
MOVH x_len+4(FP), R1 // want `invalid MOVH of x_len\+4\(FP\); slice len is 4-byte value`
|
||||
MOVW x_len+4(FP), R1
|
||||
MOVH x_cap+0(FP), R1 // want `invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)`
|
||||
MOVW x_cap+0(FP), R1 // want `invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)`
|
||||
MOVH x_cap+8(FP), R1 // want `invalid MOVH of x_cap\+8\(FP\); slice cap is 4-byte value`
|
||||
MOVW x_cap+8(FP), R1
|
||||
MOVW y+0(FP), R1 // want `invalid offset y\+0\(FP\); expected y\+12\(FP\)`
|
||||
MOVW y_len+4(FP), R1 // want `invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)`
|
||||
MOVW y_cap+8(FP), R1 // want `invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·argiface(SB),0,$0-16
|
||||
MOVH x+0(FP), R1 // want `invalid MOVH of x\+0\(FP\); interface type is 4-byte value`
|
||||
MOVW x+0(FP), R1
|
||||
MOVH x_type+0(FP), R1 // want `invalid MOVH of x_type\+0\(FP\); interface type is 4-byte value`
|
||||
MOVW x_type+0(FP), R1
|
||||
MOVQ x_itable+0(FP), R1 // want `unknown variable x_itable; offset 0 is x_type\+0\(FP\)`
|
||||
MOVQ x_itable+1(FP), R1 // want `unknown variable x_itable; offset 1 is x_type\+0\(FP\)`
|
||||
MOVH x_data+0(FP), R1 // want `invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)`
|
||||
MOVW x_data+0(FP), R1 // want `invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)`
|
||||
MOVQ x_data+0(FP), R1 // want `invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)`
|
||||
MOVH x_data+4(FP), R1 // want `invalid MOVH of x_data\+4\(FP\); interface data is 4-byte value`
|
||||
MOVW x_data+4(FP), R1
|
||||
MOVH y+8(FP), R1 // want `invalid MOVH of y\+8\(FP\); interface itable is 4-byte value`
|
||||
MOVW y+8(FP), R1
|
||||
MOVH y_itable+8(FP), R1 // want `invalid MOVH of y_itable\+8\(FP\); interface itable is 4-byte value`
|
||||
MOVW y_itable+8(FP), R1
|
||||
MOVW y_type+8(FP), AX // want `unknown variable y_type; offset 8 is y_itable\+8\(FP\)`
|
||||
MOVH y_data+8(FP), AX // want `invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)`
|
||||
MOVW y_data+8(FP), AX // want `invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)`
|
||||
MOVH y_data+12(FP), AX // want `invalid MOVH of y_data\+12\(FP\); interface data is 4-byte value`
|
||||
MOVW y_data+12(FP), AX
|
||||
RET
|
||||
|
||||
TEXT ·returnbyte(SB),0,$0-5
|
||||
MOVW x+0(FP), R1
|
||||
MOVB R1, ret+4(FP)
|
||||
MOVH R1, ret+4(FP) // want `invalid MOVH of ret\+4\(FP\); byte is 1-byte value`
|
||||
MOVW R1, ret+4(FP) // want `invalid MOVW of ret\+4\(FP\); byte is 1-byte value`
|
||||
MOVB R1, ret+3(FP) // want `invalid offset ret\+3\(FP\); expected ret\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnbyte(SB),0,$0-5
|
||||
MOVW x+0(FP), R1
|
||||
MOVB R1, ret+4(FP)
|
||||
MOVH R1, ret+4(FP) // want `invalid MOVH of ret\+4\(FP\); byte is 1-byte value`
|
||||
MOVW R1, ret+4(FP) // want `invalid MOVW of ret\+4\(FP\); byte is 1-byte value`
|
||||
MOVB R1, ret+3(FP) // want `invalid offset ret\+3\(FP\); expected ret\+4\(FP\)`
|
||||
RET
|
||||
|
||||
TEXT ·returnnamed(SB),0,$0-21
|
||||
MOVB x+0(FP), AX
|
||||
MOVW R1, r1+4(FP)
|
||||
MOVH R1, r2+8(FP)
|
||||
MOVW R1, r3+12(FP)
|
||||
MOVW R1, r3_base+12(FP)
|
||||
MOVW R1, r3_len+16(FP)
|
||||
MOVB R1, r4+20(FP)
|
||||
MOVB R1, r1+4(FP) // want `invalid MOVB of r1\+4\(FP\); int is 4-byte value`
|
||||
RET
|
||||
|
||||
TEXT ·returnintmissing(SB),0,$0-4
|
||||
RET // want `RET without writing to 4-byte ret\+0\(FP\)`
|
||||
68
vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go
generated
vendored
Normal file
68
vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// Package assign defines an Analyzer that detects useless assignments.
|
||||
package assign
|
||||
|
||||
// TODO(adonovan): check also for assignments to struct fields inside
|
||||
// methods that are on T instead of *T.
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"reflect"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
)
|
||||
|
||||
const Doc = `check for useless assignments
|
||||
|
||||
This checker reports assignments of the form x = x or a[i] = a[i].
|
||||
These are almost always useless, and even when they aren't they are
|
||||
usually a mistake.`
|
||||
|
||||
var Analyzer = &analysis.Analyzer{
|
||||
Name: "assign",
|
||||
Doc: Doc,
|
||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||
Run: run,
|
||||
}
|
||||
|
||||
func run(pass *analysis.Pass) (interface{}, error) {
|
||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||
|
||||
nodeFilter := []ast.Node{
|
||||
(*ast.AssignStmt)(nil),
|
||||
}
|
||||
inspect.Preorder(nodeFilter, func(n ast.Node) {
|
||||
stmt := n.(*ast.AssignStmt)
|
||||
if stmt.Tok != token.ASSIGN {
|
||||
return // ignore :=
|
||||
}
|
||||
if len(stmt.Lhs) != len(stmt.Rhs) {
|
||||
// If LHS and RHS have different cardinality, they can't be the same.
|
||||
return
|
||||
}
|
||||
for i, lhs := range stmt.Lhs {
|
||||
rhs := stmt.Rhs[i]
|
||||
if analysisutil.HasSideEffects(pass.TypesInfo, lhs) ||
|
||||
analysisutil.HasSideEffects(pass.TypesInfo, rhs) {
|
||||
continue // expressions may not be equal
|
||||
}
|
||||
if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) {
|
||||
continue // short-circuit the heavy-weight gofmt check
|
||||
}
|
||||
le := analysisutil.Format(pass.Fset, lhs)
|
||||
re := analysisutil.Format(pass.Fset, rhs)
|
||||
if le == re {
|
||||
pass.Reportf(stmt.Pos(), "self-assignment of %s to %s", re, le)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
17
vendor/golang.org/x/tools/go/analysis/passes/assign/assign_test.go
generated
vendored
Normal file
17
vendor/golang.org/x/tools/go/analysis/passes/assign/assign_test.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
package assign_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
"golang.org/x/tools/go/analysis/passes/assign"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
testdata := analysistest.TestData()
|
||||
analysistest.Run(t, testdata, assign.Analyzer, "a")
|
||||
}
|
||||
31
vendor/golang.org/x/tools/go/analysis/passes/assign/testdata/src/a/a.go
generated
vendored
Normal file
31
vendor/golang.org/x/tools/go/analysis/passes/assign/testdata/src/a/a.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// This file contains tests for the useless-assignment checker.
|
||||
|
||||
package testdata
|
||||
|
||||
import "math/rand"
|
||||
|
||||
type ST struct {
|
||||
x int
|
||||
l []int
|
||||
}
|
||||
|
||||
func (s *ST) SetX(x int, ch chan int) {
|
||||
// Accidental self-assignment; it should be "s.x = x"
|
||||
x = x // want "self-assignment of x to x"
|
||||
// Another mistake
|
||||
s.x = s.x // want "self-assignment of s.x to s.x"
|
||||
|
||||
s.l[0] = s.l[0] // want "self-assignment of s.l.0. to s.l.0."
|
||||
|
||||
// Bail on any potential side effects to avoid false positives
|
||||
s.l[num()] = s.l[num()]
|
||||
rng := rand.New(rand.NewSource(0))
|
||||
s.l[rng.Intn(len(s.l))] = s.l[rng.Intn(len(s.l))]
|
||||
s.l[<-ch] = s.l[<-ch]
|
||||
}
|
||||
|
||||
func num() int { return 2 }
|
||||
96
vendor/golang.org/x/tools/go/analysis/passes/atomic/atomic.go
generated
vendored
Normal file
96
vendor/golang.org/x/tools/go/analysis/passes/atomic/atomic.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// Package atomic defines an Analyzer that checks for common mistakes
|
||||
// using the sync/atomic package.
|
||||
package atomic
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
)
|
||||
|
||||
const Doc = `check for common mistakes using the sync/atomic package
|
||||
|
||||
The atomic checker looks for assignment statements of the form:
|
||||
|
||||
x = atomic.AddUint64(&x, 1)
|
||||
|
||||
which are not atomic.`
|
||||
|
||||
var Analyzer = &analysis.Analyzer{
|
||||
Name: "atomic",
|
||||
Doc: Doc,
|
||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||
RunDespiteErrors: true,
|
||||
Run: run,
|
||||
}
|
||||
|
||||
func run(pass *analysis.Pass) (interface{}, error) {
|
||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||
|
||||
nodeFilter := []ast.Node{
|
||||
(*ast.AssignStmt)(nil),
|
||||
}
|
||||
inspect.Preorder(nodeFilter, func(node ast.Node) {
|
||||
n := node.(*ast.AssignStmt)
|
||||
if len(n.Lhs) != len(n.Rhs) {
|
||||
return
|
||||
}
|
||||
if len(n.Lhs) == 1 && n.Tok == token.DEFINE {
|
||||
return
|
||||
}
|
||||
|
||||
for i, right := range n.Rhs {
|
||||
call, ok := right.(*ast.CallExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
sel, ok := call.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
pkgIdent, _ := sel.X.(*ast.Ident)
|
||||
pkgName, ok := pass.TypesInfo.Uses[pkgIdent].(*types.PkgName)
|
||||
if !ok || pkgName.Imported().Path() != "sync/atomic" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch sel.Sel.Name {
|
||||
case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr":
|
||||
checkAtomicAddAssignment(pass, n.Lhs[i], call)
|
||||
}
|
||||
}
|
||||
})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// checkAtomicAddAssignment walks the atomic.Add* method calls checking
|
||||
// for assigning the return value to the same variable being used in the
|
||||
// operation
|
||||
func checkAtomicAddAssignment(pass *analysis.Pass, left ast.Expr, call *ast.CallExpr) {
|
||||
if len(call.Args) != 2 {
|
||||
return
|
||||
}
|
||||
arg := call.Args[0]
|
||||
broken := false
|
||||
|
||||
gofmt := func(e ast.Expr) string { return analysisutil.Format(pass.Fset, e) }
|
||||
|
||||
if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND {
|
||||
broken = gofmt(left) == gofmt(uarg.X)
|
||||
} else if star, ok := left.(*ast.StarExpr); ok {
|
||||
broken = gofmt(star.X) == gofmt(arg)
|
||||
}
|
||||
|
||||
if broken {
|
||||
pass.Reportf(left.Pos(), "direct assignment to atomic value")
|
||||
}
|
||||
}
|
||||
17
vendor/golang.org/x/tools/go/analysis/passes/atomic/atomic_test.go
generated
vendored
Normal file
17
vendor/golang.org/x/tools/go/analysis/passes/atomic/atomic_test.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
package atomic_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
"golang.org/x/tools/go/analysis/passes/atomic"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
testdata := analysistest.TestData()
|
||||
analysistest.Run(t, testdata, atomic.Analyzer, "a")
|
||||
}
|
||||
62
vendor/golang.org/x/tools/go/analysis/passes/atomic/testdata/src/a/a.go
generated
vendored
Normal file
62
vendor/golang.org/x/tools/go/analysis/passes/atomic/testdata/src/a/a.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// This file contains tests for the atomic checker.
|
||||
|
||||
package a
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
type Counter uint64
|
||||
|
||||
func AtomicTests() {
|
||||
x := uint64(1)
|
||||
x = atomic.AddUint64(&x, 1) // want "direct assignment to atomic value"
|
||||
_, x = 10, atomic.AddUint64(&x, 1) // want "direct assignment to atomic value"
|
||||
x, _ = atomic.AddUint64(&x, 1), 10 // want "direct assignment to atomic value"
|
||||
|
||||
y := &x
|
||||
*y = atomic.AddUint64(y, 1) // want "direct assignment to atomic value"
|
||||
|
||||
var su struct{ Counter uint64 }
|
||||
su.Counter = atomic.AddUint64(&su.Counter, 1) // want "direct assignment to atomic value"
|
||||
z1 := atomic.AddUint64(&su.Counter, 1)
|
||||
_ = z1 // Avoid err "z declared and not used"
|
||||
|
||||
var sp struct{ Counter *uint64 }
|
||||
*sp.Counter = atomic.AddUint64(sp.Counter, 1) // want "direct assignment to atomic value"
|
||||
z2 := atomic.AddUint64(sp.Counter, 1)
|
||||
_ = z2 // Avoid err "z declared and not used"
|
||||
|
||||
au := []uint64{10, 20}
|
||||
au[0] = atomic.AddUint64(&au[0], 1) // want "direct assignment to atomic value"
|
||||
au[1] = atomic.AddUint64(&au[0], 1)
|
||||
|
||||
ap := []*uint64{&au[0], &au[1]}
|
||||
*ap[0] = atomic.AddUint64(ap[0], 1) // want "direct assignment to atomic value"
|
||||
*ap[1] = atomic.AddUint64(ap[0], 1)
|
||||
|
||||
x = atomic.AddUint64() // Used to make vet crash; now silently ignored.
|
||||
|
||||
{
|
||||
// A variable declaration creates a new variable in the current scope.
|
||||
x := atomic.AddUint64(&x, 1)
|
||||
|
||||
// Re-declaration assigns a new value.
|
||||
x, w := atomic.AddUint64(&x, 1), 10 // want "direct assignment to atomic value"
|
||||
_ = w
|
||||
}
|
||||
}
|
||||
|
||||
type T struct{}
|
||||
|
||||
func (T) AddUint64(addr *uint64, delta uint64) uint64 { return 0 }
|
||||
|
||||
func NonAtomic() {
|
||||
x := uint64(1)
|
||||
var atomic T
|
||||
x = atomic.AddUint64(&x, 1) // ok; not the imported pkg
|
||||
}
|
||||
214
vendor/golang.org/x/tools/go/analysis/passes/bools/bools.go
generated
vendored
Normal file
214
vendor/golang.org/x/tools/go/analysis/passes/bools/bools.go
generated
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Package bools defines an Analyzer that detects common mistakes
|
||||
// involving boolean operators.
|
||||
package bools
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
)
|
||||
|
||||
var Analyzer = &analysis.Analyzer{
|
||||
Name: "bools",
|
||||
Doc: "check for common mistakes involving boolean operators",
|
||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||
Run: run,
|
||||
}
|
||||
|
||||
func run(pass *analysis.Pass) (interface{}, error) {
|
||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||
|
||||
nodeFilter := []ast.Node{
|
||||
(*ast.BinaryExpr)(nil),
|
||||
}
|
||||
inspect.Preorder(nodeFilter, func(n ast.Node) {
|
||||
e := n.(*ast.BinaryExpr)
|
||||
|
||||
var op boolOp
|
||||
switch e.Op {
|
||||
case token.LOR:
|
||||
op = or
|
||||
case token.LAND:
|
||||
op = and
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(adonovan): this reports n(n-1)/2 errors for an
|
||||
// expression e||...||e of depth n. Fix.
|
||||
// See https://github.com/golang/go/issues/28086.
|
||||
comm := op.commutativeSets(pass.TypesInfo, e)
|
||||
for _, exprs := range comm {
|
||||
op.checkRedundant(pass, exprs)
|
||||
op.checkSuspect(pass, exprs)
|
||||
}
|
||||
})
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type boolOp struct {
|
||||
name string
|
||||
tok token.Token // token corresponding to this operator
|
||||
badEq token.Token // token corresponding to the equality test that should not be used with this operator
|
||||
}
|
||||
|
||||
var (
|
||||
or = boolOp{"or", token.LOR, token.NEQ}
|
||||
and = boolOp{"and", token.LAND, token.EQL}
|
||||
)
|
||||
|
||||
// commutativeSets returns all side effect free sets of
|
||||
// expressions in e that are connected by op.
|
||||
// For example, given 'a || b || f() || c || d' with the or op,
|
||||
// commutativeSets returns {{b, a}, {d, c}}.
|
||||
func (op boolOp) commutativeSets(info *types.Info, e *ast.BinaryExpr) [][]ast.Expr {
|
||||
exprs := op.split(e)
|
||||
|
||||
// Partition the slice of expressions into commutative sets.
|
||||
i := 0
|
||||
var sets [][]ast.Expr
|
||||
for j := 0; j <= len(exprs); j++ {
|
||||
if j == len(exprs) || hasSideEffects(info, exprs[j]) {
|
||||
if i < j {
|
||||
sets = append(sets, exprs[i:j])
|
||||
}
|
||||
i = j + 1
|
||||
}
|
||||
}
|
||||
|
||||
return sets
|
||||
}
|
||||
|
||||
// checkRedundant checks for expressions of the form
|
||||
// e && e
|
||||
// e || e
|
||||
// Exprs must contain only side effect free expressions.
|
||||
func (op boolOp) checkRedundant(pass *analysis.Pass, exprs []ast.Expr) {
|
||||
seen := make(map[string]bool)
|
||||
for _, e := range exprs {
|
||||
efmt := analysisutil.Format(pass.Fset, e)
|
||||
if seen[efmt] {
|
||||
pass.Reportf(e.Pos(), "redundant %s: %s %s %s", op.name, efmt, op.tok, efmt)
|
||||
} else {
|
||||
seen[efmt] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checkSuspect checks for expressions of the form
|
||||
// x != c1 || x != c2
|
||||
// x == c1 && x == c2
|
||||
// where c1 and c2 are constant expressions.
|
||||
// If c1 and c2 are the same then it's redundant;
|
||||
// if c1 and c2 are different then it's always true or always false.
|
||||
// Exprs must contain only side effect free expressions.
|
||||
func (op boolOp) checkSuspect(pass *analysis.Pass, exprs []ast.Expr) {
|
||||
// seen maps from expressions 'x' to equality expressions 'x != c'.
|
||||
seen := make(map[string]string)
|
||||
|
||||
for _, e := range exprs {
|
||||
bin, ok := e.(*ast.BinaryExpr)
|
||||
if !ok || bin.Op != op.badEq {
|
||||
continue
|
||||
}
|
||||
|
||||
// In order to avoid false positives, restrict to cases
|
||||
// in which one of the operands is constant. We're then
|
||||
// interested in the other operand.
|
||||
// In the rare case in which both operands are constant
|
||||
// (e.g. runtime.GOOS and "windows"), we'll only catch
|
||||
// mistakes if the LHS is repeated, which is how most
|
||||
// code is written.
|
||||
var x ast.Expr
|
||||
switch {
|
||||
case pass.TypesInfo.Types[bin.Y].Value != nil:
|
||||
x = bin.X
|
||||
case pass.TypesInfo.Types[bin.X].Value != nil:
|
||||
x = bin.Y
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
// e is of the form 'x != c' or 'x == c'.
|
||||
xfmt := analysisutil.Format(pass.Fset, x)
|
||||
efmt := analysisutil.Format(pass.Fset, e)
|
||||
if prev, found := seen[xfmt]; found {
|
||||
// checkRedundant handles the case in which efmt == prev.
|
||||
if efmt != prev {
|
||||
pass.Reportf(e.Pos(), "suspect %s: %s %s %s", op.name, efmt, op.tok, prev)
|
||||
}
|
||||
} else {
|
||||
seen[xfmt] = efmt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hasSideEffects reports whether evaluation of e has side effects.
|
||||
func hasSideEffects(info *types.Info, e ast.Expr) bool {
|
||||
safe := true
|
||||
ast.Inspect(e, func(node ast.Node) bool {
|
||||
switch n := node.(type) {
|
||||
case *ast.CallExpr:
|
||||
typVal := info.Types[n.Fun]
|
||||
switch {
|
||||
case typVal.IsType():
|
||||
// Type conversion, which is safe.
|
||||
case typVal.IsBuiltin():
|
||||
// Builtin func, conservatively assumed to not
|
||||
// be safe for now.
|
||||
safe = false
|
||||
return false
|
||||
default:
|
||||
// A non-builtin func or method call.
|
||||
// Conservatively assume that all of them have
|
||||
// side effects for now.
|
||||
safe = false
|
||||
return false
|
||||
}
|
||||
case *ast.UnaryExpr:
|
||||
if n.Op == token.ARROW {
|
||||
safe = false
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
return !safe
|
||||
}
|
||||
|
||||
// split returns a slice of all subexpressions in e that are connected by op.
|
||||
// For example, given 'a || (b || c) || d' with the or op,
|
||||
// split returns []{d, c, b, a}.
|
||||
func (op boolOp) split(e ast.Expr) (exprs []ast.Expr) {
|
||||
for {
|
||||
e = unparen(e)
|
||||
if b, ok := e.(*ast.BinaryExpr); ok && b.Op == op.tok {
|
||||
exprs = append(exprs, op.split(b.Y)...)
|
||||
e = b.X
|
||||
} else {
|
||||
exprs = append(exprs, e)
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// unparen returns e with any enclosing parentheses stripped.
|
||||
func unparen(e ast.Expr) ast.Expr {
|
||||
for {
|
||||
p, ok := e.(*ast.ParenExpr)
|
||||
if !ok {
|
||||
return e
|
||||
}
|
||||
e = p.X
|
||||
}
|
||||
}
|
||||
17
vendor/golang.org/x/tools/go/analysis/passes/bools/bools_test.go
generated
vendored
Normal file
17
vendor/golang.org/x/tools/go/analysis/passes/bools/bools_test.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
package bools_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
"golang.org/x/tools/go/analysis/passes/bools"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
testdata := analysistest.TestData()
|
||||
analysistest.Run(t, testdata, bools.Analyzer, "a")
|
||||
}
|
||||
137
vendor/golang.org/x/tools/go/analysis/passes/bools/testdata/src/a/a.go
generated
vendored
Normal file
137
vendor/golang.org/x/tools/go/analysis/passes/bools/testdata/src/a/a.go
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// This file contains tests for the bool checker.
|
||||
|
||||
package a
|
||||
|
||||
import "io"
|
||||
|
||||
type T int
|
||||
|
||||
func (t T) Foo() int { return int(t) }
|
||||
|
||||
type FT func() int
|
||||
|
||||
var S []int
|
||||
|
||||
func RatherStupidConditions() {
|
||||
var f, g func() int
|
||||
if f() == 0 || f() == 0 { // OK f might have side effects
|
||||
}
|
||||
var t T
|
||||
_ = t.Foo() == 2 || t.Foo() == 2 // OK Foo might have side effects
|
||||
if v, w := f(), g(); v == w || v == w { // want `redundant or: v == w \|\| v == w`
|
||||
}
|
||||
_ = f == nil || f == nil // want `redundant or: f == nil \|\| f == nil`
|
||||
|
||||
var B byte
|
||||
_ = B == byte(1) || B == byte(1) // want `redundant or: B == byte\(1\) \|\| B == byte\(1\)`
|
||||
_ = t == T(2) || t == T(2) // want `redundant or: t == T\(2\) \|\| t == T\(2\)`
|
||||
_ = FT(f) == nil || FT(f) == nil // want `redundant or: FT\(f\) == nil \|\| FT\(f\) == nil`
|
||||
|
||||
_ = (func() int)(f) == nil || (func() int)(f) == nil // want `redundant or: \(func\(\) int\)\(f\) == nil \|\| \(func\(\) int\)\(f\) == nil`
|
||||
_ = append(S, 3) == nil || append(S, 3) == nil // OK append has side effects
|
||||
|
||||
var namedFuncVar FT
|
||||
_ = namedFuncVar() == namedFuncVar() // OK still func calls
|
||||
|
||||
var c chan int
|
||||
_ = 0 == <-c || 0 == <-c // OK subsequent receives may yield different values
|
||||
for i, j := <-c, <-c; i == j || i == j; i, j = <-c, <-c { // want `redundant or: i == j \|\| i == j`
|
||||
}
|
||||
|
||||
var i, j, k int
|
||||
_ = i+1 == 1 || i+1 == 1 // want `redundant or: i\+1 == 1 \|\| i\+1 == 1`
|
||||
_ = i == 1 || j+1 == i || i == 1 // want `redundant or: i == 1 \|\| i == 1`
|
||||
|
||||
// The various r.* patterns are intended to match duplicate
|
||||
// diagnostics reported for the same underlying problem.
|
||||
// See github.com/golang/go/issues/28086.
|
||||
// TODO(adonovan): fix the checker.
|
||||
|
||||
_ = i == 1 || i == 1 || f() == 1 // want `redundant or: i == 1 \|\| i == 1` `r.*`
|
||||
_ = i == 1 || f() == 1 || i == 1 // OK f may alter i as a side effect
|
||||
_ = f() == 1 || i == 1 || i == 1 // want `redundant or: i == 1 \|\| i == 1`
|
||||
|
||||
// Test partition edge cases
|
||||
_ = f() == 1 || i == 1 || i == 1 || j == 1 // want `redundant or: i == 1 \|\| i == 1` `r.*`
|
||||
_ = f() == 1 || j == 1 || i == 1 || i == 1 // want `redundant or: i == 1 \|\| i == 1`
|
||||
_ = i == 1 || f() == 1 || i == 1 || i == 1 // want `redundant or: i == 1 \|\| i == 1`
|
||||
_ = i == 1 || i == 1 || f() == 1 || i == 1 // want `redundant or: i == 1 \|\| i == 1` `r.*` `r.*`
|
||||
_ = i == 1 || i == 1 || j == 1 || f() == 1 // want `redundant or: i == 1 \|\| i == 1` `r.*` `r.*`
|
||||
_ = j == 1 || i == 1 || i == 1 || f() == 1 // want `redundant or: i == 1 \|\| i == 1` `r.*`
|
||||
_ = i == 1 || f() == 1 || f() == 1 || i == 1
|
||||
|
||||
_ = i == 1 || (i == 1 || i == 2) // want `redundant or: i == 1 \|\| i == 1`
|
||||
_ = i == 1 || (f() == 1 || i == 1) // OK f may alter i as a side effect
|
||||
_ = i == 1 || (i == 1 || f() == 1) // want `redundant or: i == 1 \|\| i == 1`
|
||||
_ = i == 1 || (i == 2 || (i == 1 || i == 3)) // want `redundant or: i == 1 \|\| i == 1`
|
||||
|
||||
var a, b bool
|
||||
_ = i == 1 || (a || (i == 1 || b)) // want `redundant or: i == 1 \|\| i == 1`
|
||||
|
||||
// Check that all redundant ors are flagged
|
||||
_ = j == 0 ||
|
||||
i == 1 ||
|
||||
f() == 1 ||
|
||||
j == 0 || // want `redundant or: j == 0 \|\| j == 0` `r.*`
|
||||
i == 1 || // want `redundant or: i == 1 \|\| i == 1` `r.*` `r.*` `r.*`
|
||||
i == 1 || // want `redundant or: i == 1 \|\| i == 1` `r.*` `r.*`
|
||||
i == 1 ||
|
||||
j == 0 ||
|
||||
k == 0
|
||||
|
||||
_ = i == 1*2*3 || i == 1*2*3 // want `redundant or: i == 1\*2\*3 \|\| i == 1\*2\*3`
|
||||
|
||||
// These test that redundant, suspect expressions do not trigger multiple errors.
|
||||
_ = i != 0 || i != 0 // want `redundant or: i != 0 \|\| i != 0`
|
||||
_ = i == 0 && i == 0 // want `redundant and: i == 0 && i == 0`
|
||||
|
||||
// and is dual to or; check the basics and
|
||||
// let the or tests pull the rest of the weight.
|
||||
_ = 0 != <-c && 0 != <-c // OK subsequent receives may yield different values
|
||||
_ = f() != 0 && f() != 0 // OK f might have side effects
|
||||
_ = f != nil && f != nil // want `redundant and: f != nil && f != nil`
|
||||
_ = i != 1 && i != 1 && f() != 1 // want `redundant and: i != 1 && i != 1` `r.*`
|
||||
_ = i != 1 && f() != 1 && i != 1 // OK f may alter i as a side effect
|
||||
_ = f() != 1 && i != 1 && i != 1 // want `redundant and: i != 1 && i != 1`
|
||||
}
|
||||
|
||||
func RoyallySuspectConditions() {
|
||||
var i, j int
|
||||
|
||||
_ = i == 0 || i == 1 // OK
|
||||
_ = i != 0 || i != 1 // want `suspect or: i != 0 \|\| i != 1`
|
||||
_ = i != 0 || 1 != i // want `suspect or: i != 0 \|\| 1 != i`
|
||||
_ = 0 != i || 1 != i // want `suspect or: 0 != i \|\| 1 != i`
|
||||
_ = 0 != i || i != 1 // want `suspect or: 0 != i \|\| i != 1`
|
||||
|
||||
_ = (0 != i) || i != 1 // want `suspect or: 0 != i \|\| i != 1`
|
||||
|
||||
_ = i+3 != 7 || j+5 == 0 || i+3 != 9 // want `suspect or: i\+3 != 7 \|\| i\+3 != 9`
|
||||
|
||||
_ = i != 0 || j == 0 || i != 1 // want `suspect or: i != 0 \|\| i != 1`
|
||||
|
||||
_ = i != 0 || i != 1<<4 // want `suspect or: i != 0 \|\| i != 1<<4`
|
||||
|
||||
_ = i != 0 || j != 0
|
||||
_ = 0 != i || 0 != j
|
||||
|
||||
var s string
|
||||
_ = s != "one" || s != "the other" // want `suspect or: s != .one. \|\| s != .the other.`
|
||||
|
||||
_ = "et" != "alii" || "et" != "cetera" // want `suspect or: .et. != .alii. \|\| .et. != .cetera.`
|
||||
_ = "me gustas" != "tu" || "le gustas" != "tu" // OK we could catch this case, but it's not worth the code
|
||||
|
||||
var err error
|
||||
_ = err != nil || err != io.EOF // TODO catch this case?
|
||||
|
||||
// Sanity check and.
|
||||
_ = i != 0 && i != 1 // OK
|
||||
_ = i == 0 && i == 1 // want `suspect and: i == 0 && i == 1`
|
||||
_ = i == 0 && 1 == i // want `suspect and: i == 0 && 1 == i`
|
||||
_ = 0 == i && 1 == i // want `suspect and: 0 == i && 1 == i`
|
||||
_ = 0 == i && i == 1 // want `suspect and: 0 == i && i == 1`
|
||||
}
|
||||
117
vendor/golang.org/x/tools/go/analysis/passes/buildssa/buildssa.go
generated
vendored
Normal file
117
vendor/golang.org/x/tools/go/analysis/passes/buildssa/buildssa.go
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// Package buildssa defines an Analyzer that constructs the SSA
|
||||
// representation of an error-free package and returns the set of all
|
||||
// functions within it. It does not report any diagnostics itself but
|
||||
// may be used as an input to other analyzers.
|
||||
//
|
||||
// THIS INTERFACE IS EXPERIMENTAL AND MAY BE SUBJECT TO INCOMPATIBLE CHANGE.
|
||||
package buildssa
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
"reflect"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/ssa"
|
||||
)
|
||||
|
||||
var Analyzer = &analysis.Analyzer{
|
||||
Name: "buildssa",
|
||||
Doc: "build SSA-form IR for later passes",
|
||||
Run: run,
|
||||
ResultType: reflect.TypeOf(new(SSA)),
|
||||
}
|
||||
|
||||
// SSA provides SSA-form intermediate representation for all the
|
||||
// non-blank source functions in the current package.
|
||||
type SSA struct {
|
||||
Pkg *ssa.Package
|
||||
SrcFuncs []*ssa.Function
|
||||
}
|
||||
|
||||
func run(pass *analysis.Pass) (interface{}, error) {
|
||||
// Plundered from ssautil.BuildPackage.
|
||||
|
||||
// We must create a new Program for each Package because the
|
||||
// analysis API provides no place to hang a Program shared by
|
||||
// all Packages. Consequently, SSA Packages and Functions do not
|
||||
// have a canonical representation across an analysis session of
|
||||
// multiple packages. This is unlikely to be a problem in
|
||||
// practice because the analysis API essentially forces all
|
||||
// packages to be analysed independently, so any given call to
|
||||
// Analysis.Run on a package will see only SSA objects belonging
|
||||
// to a single Program.
|
||||
|
||||
// Some Analyzers may need GlobalDebug, in which case we'll have
|
||||
// to set it globally, but let's wait till we need it.
|
||||
mode := ssa.BuilderMode(0)
|
||||
|
||||
prog := ssa.NewProgram(pass.Fset, mode)
|
||||
|
||||
// Create SSA packages for all imports.
|
||||
// Order is not significant.
|
||||
created := make(map[*types.Package]bool)
|
||||
var createAll func(pkgs []*types.Package)
|
||||
createAll = func(pkgs []*types.Package) {
|
||||
for _, p := range pkgs {
|
||||
if !created[p] {
|
||||
created[p] = true
|
||||
prog.CreatePackage(p, nil, nil, true)
|
||||
createAll(p.Imports())
|
||||
}
|
||||
}
|
||||
}
|
||||
createAll(pass.Pkg.Imports())
|
||||
|
||||
// Create and build the primary package.
|
||||
ssapkg := prog.CreatePackage(pass.Pkg, pass.Files, pass.TypesInfo, false)
|
||||
ssapkg.Build()
|
||||
|
||||
// Compute list of source functions, including literals,
|
||||
// in source order.
|
||||
var funcs []*ssa.Function
|
||||
for _, f := range pass.Files {
|
||||
for _, decl := range f.Decls {
|
||||
if fdecl, ok := decl.(*ast.FuncDecl); ok {
|
||||
|
||||
// SSA will not build a Function
|
||||
// for a FuncDecl named blank.
|
||||
// That's arguably too strict but
|
||||
// relaxing it would break uniqueness of
|
||||
// names of package members.
|
||||
if fdecl.Name.Name == "_" {
|
||||
continue
|
||||
}
|
||||
|
||||
// (init functions have distinct Func
|
||||
// objects named "init" and distinct
|
||||
// ssa.Functions named "init#1", ...)
|
||||
|
||||
fn := pass.TypesInfo.Defs[fdecl.Name].(*types.Func)
|
||||
if fn == nil {
|
||||
panic(fn)
|
||||
}
|
||||
|
||||
f := ssapkg.Prog.FuncValue(fn)
|
||||
if f == nil {
|
||||
panic(fn)
|
||||
}
|
||||
|
||||
var addAnons func(f *ssa.Function)
|
||||
addAnons = func(f *ssa.Function) {
|
||||
funcs = append(funcs, f)
|
||||
for _, anon := range f.AnonFuncs {
|
||||
addAnons(anon)
|
||||
}
|
||||
}
|
||||
addAnons(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &SSA{Pkg: ssapkg, SrcFuncs: funcs}, nil
|
||||
}
|
||||
29
vendor/golang.org/x/tools/go/analysis/passes/buildssa/buildssa_test.go
generated
vendored
Normal file
29
vendor/golang.org/x/tools/go/analysis/passes/buildssa/buildssa_test.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
package buildssa_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
"golang.org/x/tools/go/analysis/passes/buildssa"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
testdata := analysistest.TestData()
|
||||
result := analysistest.Run(t, testdata, buildssa.Analyzer, "a")[0].Result
|
||||
|
||||
ssainfo := result.(*buildssa.SSA)
|
||||
got := fmt.Sprint(ssainfo.SrcFuncs)
|
||||
want := `[a.Fib (a.T).fib]`
|
||||
if got != want {
|
||||
t.Errorf("SSA.SrcFuncs = %s, want %s", got, want)
|
||||
for _, f := range ssainfo.SrcFuncs {
|
||||
f.WriteTo(os.Stderr)
|
||||
}
|
||||
}
|
||||
}
|
||||
16
vendor/golang.org/x/tools/go/analysis/passes/buildssa/testdata/src/a/a.go
generated
vendored
Normal file
16
vendor/golang.org/x/tools/go/analysis/passes/buildssa/testdata/src/a/a.go
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
package a
|
||||
|
||||
func Fib(x int) int {
|
||||
if x < 2 {
|
||||
return x
|
||||
}
|
||||
return Fib(x-1) + Fib(x-2)
|
||||
}
|
||||
|
||||
type T int
|
||||
|
||||
func (T) fib(x int) int { return Fib(x) }
|
||||
|
||||
func _() {
|
||||
print("hi")
|
||||
}
|
||||
159
vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go
generated
vendored
Normal file
159
vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go
generated
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// Package buildtag defines an Analyzer that checks build tags.
|
||||
package buildtag
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
|
||||
)
|
||||
|
||||
var Analyzer = &analysis.Analyzer{
|
||||
Name: "buildtag",
|
||||
Doc: "check that +build tags are well-formed and correctly located",
|
||||
Run: runBuildTag,
|
||||
}
|
||||
|
||||
func runBuildTag(pass *analysis.Pass) (interface{}, error) {
|
||||
for _, f := range pass.Files {
|
||||
checkGoFile(pass, f)
|
||||
}
|
||||
for _, name := range pass.OtherFiles {
|
||||
if err := checkOtherFile(pass, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func checkGoFile(pass *analysis.Pass, f *ast.File) {
|
||||
pastCutoff := false
|
||||
for _, group := range f.Comments {
|
||||
// A +build comment is ignored after or adjoining the package declaration.
|
||||
if group.End()+1 >= f.Package {
|
||||
pastCutoff = true
|
||||
}
|
||||
|
||||
// "+build" is ignored within or after a /*...*/ comment.
|
||||
if !strings.HasPrefix(group.List[0].Text, "//") {
|
||||
pastCutoff = true
|
||||
continue
|
||||
}
|
||||
|
||||
// Check each line of a //-comment.
|
||||
for _, c := range group.List {
|
||||
if !strings.Contains(c.Text, "+build") {
|
||||
continue
|
||||
}
|
||||
if err := checkLine(c.Text, pastCutoff); err != nil {
|
||||
pass.Reportf(c.Pos(), "%s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkOtherFile(pass *analysis.Pass, filename string) error {
|
||||
content, tf, err := analysisutil.ReadFile(pass.Fset, filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We must look at the raw lines, as build tags may appear in non-Go
|
||||
// files such as assembly files.
|
||||
lines := bytes.SplitAfter(content, nl)
|
||||
|
||||
// Determine cutpoint where +build comments are no longer valid.
|
||||
// They are valid in leading // comments in the file followed by
|
||||
// a blank line.
|
||||
//
|
||||
// This must be done as a separate pass because of the
|
||||
// requirement that the comment be followed by a blank line.
|
||||
var cutoff int
|
||||
for i, line := range lines {
|
||||
line = bytes.TrimSpace(line)
|
||||
if !bytes.HasPrefix(line, slashSlash) {
|
||||
if len(line) > 0 {
|
||||
break
|
||||
}
|
||||
cutoff = i
|
||||
}
|
||||
}
|
||||
|
||||
for i, line := range lines {
|
||||
line = bytes.TrimSpace(line)
|
||||
if !bytes.HasPrefix(line, slashSlash) {
|
||||
continue
|
||||
}
|
||||
if !bytes.Contains(line, []byte("+build")) {
|
||||
continue
|
||||
}
|
||||
if err := checkLine(string(line), i >= cutoff); err != nil {
|
||||
pass.Reportf(analysisutil.LineStart(tf, i+1), "%s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkLine checks a line that starts with "//" and contains "+build".
|
||||
func checkLine(line string, pastCutoff bool) error {
|
||||
line = strings.TrimPrefix(line, "//")
|
||||
line = strings.TrimSpace(line)
|
||||
|
||||
if strings.HasPrefix(line, "+build") {
|
||||
fields := strings.Fields(line)
|
||||
if fields[0] != "+build" {
|
||||
// Comment is something like +buildasdf not +build.
|
||||
return fmt.Errorf("possible malformed +build comment")
|
||||
}
|
||||
if pastCutoff {
|
||||
return fmt.Errorf("+build comment must appear before package clause and be followed by a blank line")
|
||||
}
|
||||
if err := checkArguments(fields); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Comment with +build but not at beginning.
|
||||
if !pastCutoff {
|
||||
return fmt.Errorf("possible malformed +build comment")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkArguments(fields []string) error {
|
||||
// The original version of this checker in vet could examine
|
||||
// files with malformed build tags that would cause the file to
|
||||
// be always ignored by "go build". However, drivers for the new
|
||||
// analysis API will analyze only the files selected to form a
|
||||
// package, so these checks will never fire.
|
||||
// TODO(adonovan): rethink this.
|
||||
|
||||
for _, arg := range fields[1:] {
|
||||
for _, elem := range strings.Split(arg, ",") {
|
||||
if strings.HasPrefix(elem, "!!") {
|
||||
return fmt.Errorf("invalid double negative in build constraint: %s", arg)
|
||||
}
|
||||
elem = strings.TrimPrefix(elem, "!")
|
||||
for _, c := range elem {
|
||||
if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
|
||||
return fmt.Errorf("invalid non-alphanumeric build constraint: %s", arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
nl = []byte("\n")
|
||||
slashSlash = []byte("//")
|
||||
)
|
||||
17
vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_test.go
generated
vendored
Normal file
17
vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_test.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
package buildtag_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
"golang.org/x/tools/go/analysis/passes/buildtag"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
testdata := analysistest.TestData()
|
||||
analysistest.Run(t, testdata, buildtag.Analyzer, "a")
|
||||
}
|
||||
21
vendor/golang.org/x/tools/go/analysis/passes/buildtag/testdata/src/a/buildtag.go
generated
vendored
Normal file
21
vendor/golang.org/x/tools/go/analysis/passes/buildtag/testdata/src/a/buildtag.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// This file contains tests for the buildtag checker.
|
||||
|
||||
// +builder // want `possible malformed \+build comment`
|
||||
// +build !ignore
|
||||
|
||||
// Mention +build // want `possible malformed \+build comment`
|
||||
|
||||
// +build nospace // want "build comment must appear before package clause and be followed by a blank line"
|
||||
package a
|
||||
|
||||
// +build toolate // want "build comment must appear before package clause and be followed by a blank line$"
|
||||
|
||||
var _ = 3
|
||||
|
||||
var _ = `
|
||||
// +build notacomment
|
||||
`
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user