aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/vendor/golang.org/x/tools/go/analysis/passes
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/vendor/golang.org/x/tools/go/analysis/passes')
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go2
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go2
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go2
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go7
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/directive/directive.go11
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go2
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go11
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/doc.go60
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdversion/stdversion.go159
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go15
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go19
11 files changed, 253 insertions, 37 deletions
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
index f2ca95aa9e..3417232ce3 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
@@ -173,7 +173,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
Files:
for _, fname := range sfiles {
- content, tf, err := analysisutil.ReadFile(pass.Fset, fname)
+ content, tf, err := analysisutil.ReadFile(pass, fname)
if err != nil {
return nil, err
}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go
index 55bdad78b7..51ba2a91e5 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go
@@ -89,7 +89,7 @@ func checkOtherFile(pass *analysis.Pass, filename string) error {
// We cannot use the Go parser, since this may not be a Go source file.
// Read the raw bytes instead.
- content, tf, err := analysisutil.ReadFile(pass.Fset, filename)
+ content, tf, err := analysisutil.ReadFile(pass, filename)
if err != nil {
return err
}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go
index 0001ba5363..19ef6b9bce 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go
@@ -83,7 +83,7 @@ func checkGoFile(pass *analysis.Pass, f *ast.File) {
}
func checkOtherFile(pass *analysis.Pass, filename string) error {
- content, tf, err := analysisutil.ReadFile(pass.Fset, filename)
+ content, tf, err := analysisutil.ReadFile(pass, filename)
if err != nil {
return err
}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go
index 8f39159c0f..8f6e7db6a2 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go
@@ -31,7 +31,7 @@ values should be referred to through a pointer.`
var Analyzer = &analysis.Analyzer{
Name: "copylocks",
Doc: Doc,
- URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/copylocks",
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/copylock",
Requires: []*analysis.Analyzer{inspect.Analyzer},
RunDespiteErrors: true,
Run: run,
@@ -240,7 +240,10 @@ func lockPathRhs(pass *analysis.Pass, x ast.Expr) typePath {
return nil
}
}
- return lockPath(pass.Pkg, pass.TypesInfo.Types[x].Type, nil)
+ if tv, ok := pass.TypesInfo.Types[x]; ok && tv.IsValue() {
+ return lockPath(pass.Pkg, tv.Type, nil)
+ }
+ return nil
}
// lockPath returns a typePath describing the location of a lock value
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/directive/directive.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/directive/directive.go
index 2691f189aa..b205402388 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/directive/directive.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/directive/directive.go
@@ -70,11 +70,7 @@ func checkGoFile(pass *analysis.Pass, f *ast.File) {
check := newChecker(pass, pass.Fset.File(f.Package).Name(), f)
for _, group := range f.Comments {
- // A +build comment is ignored after or adjoining the package declaration.
- if group.End()+1 >= f.Package {
- check.inHeader = false
- }
- // A //go:build comment is ignored after the package declaration
+ // A //go:build or a //go:debug comment is ignored after the package declaration
// (but adjoining it is OK, in contrast to +build comments).
if group.Pos() >= f.Package {
check.inHeader = false
@@ -90,7 +86,7 @@ func checkGoFile(pass *analysis.Pass, f *ast.File) {
func checkOtherFile(pass *analysis.Pass, filename string) error {
// We cannot use the Go parser, since is not a Go source file.
// Read the raw bytes instead.
- content, tf, err := analysisutil.ReadFile(pass.Fset, filename)
+ content, tf, err := analysisutil.ReadFile(pass, filename)
if err != nil {
return err
}
@@ -104,8 +100,7 @@ type checker struct {
pass *analysis.Pass
filename string
file *ast.File // nil for non-Go file
- inHeader bool // in file header (before package declaration)
- inStar bool // currently in a /* */ comment
+ inHeader bool // in file header (before or adjoining package declaration)
}
func newChecker(pass *analysis.Pass, filename string, file *ast.File) *checker {
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go
index 0b3ded47ea..6eff3a20fe 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go
@@ -48,7 +48,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
}
for _, fname := range sfiles {
- content, tf, err := analysisutil.ReadFile(pass.Fset, fname)
+ content, tf, err := analysisutil.ReadFile(pass, fname)
if err != nil {
return nil, err
}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go
index 89291602a5..f7f071dc8b 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go
@@ -14,6 +14,7 @@ import (
"go/types"
"os"
+ "golang.org/x/tools/go/analysis"
"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/analysisinternal"
)
@@ -60,12 +61,16 @@ func HasSideEffects(info *types.Info, e ast.Expr) bool {
// ReadFile reads a file and adds it to the FileSet
// so that we can report errors against it using lineStart.
-func ReadFile(fset *token.FileSet, filename string) ([]byte, *token.File, error) {
- content, err := os.ReadFile(filename)
+func ReadFile(pass *analysis.Pass, filename string) ([]byte, *token.File, error) {
+ readFile := pass.ReadFile
+ if readFile == nil {
+ readFile = os.ReadFile
+ }
+ content, err := readFile(filename)
if err != nil {
return nil, nil, err
}
- tf := fset.AddFile(filename, -1, len(content))
+ tf := pass.Fset.AddFile(filename, -1, len(content))
tf.SetLinesForContent(content)
return content, tf, nil
}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/doc.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/doc.go
index 1ee16126ad..85da8346f7 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/doc.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/doc.go
@@ -11,14 +11,53 @@
//
// The check applies to calls of the formatting functions such as
// [fmt.Printf] and [fmt.Sprintf], as well as any detected wrappers of
-// those functions.
+// those functions such as [log.Printf]. It reports a variety of
+// mistakes such as syntax errors in the format string and mismatches
+// (of number and type) between the verbs and their arguments.
//
-// In this example, the %d format operator requires an integer operand:
+// See the documentation of the fmt package for the complete set of
+// format operators and their operand types.
+//
+// # Examples
+//
+// The %d format operator requires an integer operand.
+// Here it is incorrectly applied to a string:
//
// fmt.Printf("%d", "hello") // fmt.Printf format %d has arg "hello" of wrong type string
//
-// See the documentation of the fmt package for the complete set of
-// format operators and their operand types.
+// A call to Printf must have as many operands as there are "verbs" in
+// the format string, not too few:
+//
+// fmt.Printf("%d") // fmt.Printf format reads arg 1, but call has 0 args
+//
+// nor too many:
+//
+// fmt.Printf("%d", 1, 2) // fmt.Printf call needs 1 arg, but has 2 args
+//
+// Explicit argument indexes must be no greater than the number of
+// arguments:
+//
+// fmt.Printf("%[3]d", 1, 2) // fmt.Printf call has invalid argument index 3
+//
+// The checker also uses a heuristic to report calls to Print-like
+// functions that appear to have been intended for their Printf-like
+// counterpart:
+//
+// log.Print("%d", 123) // log.Print call has possible formatting directive %d
+//
+// # Inferred printf wrappers
+//
+// Functions that delegate their arguments to fmt.Printf are
+// considered "printf wrappers"; calls to them are subject to the same
+// checking. In this example, logf is a printf wrapper:
+//
+// func logf(level int, format string, args ...any) {
+// if enabled(level) {
+// log.Printf(format, args...)
+// }
+// }
+//
+// logf(3, "invalid request: %v") // logf format reads arg 1, but call has 0 args
//
// To enable printf checking on a function that is not found by this
// analyzer's heuristics (for example, because control is obscured by
@@ -26,14 +65,19 @@
//
// func MyPrintf(format string, args ...any) {
// if false {
-// _ = fmt.Sprintf(format, args...) // enable printf checker
+// _ = fmt.Sprintf(format, args...) // enable printf checking
// }
// ...
// }
//
-// The -funcs flag specifies a comma-separated list of names of additional
-// known formatting functions or methods. If the name contains a period,
-// it must denote a specific function using one of the following forms:
+// # Specifying printf wrappers by flag
+//
+// The -funcs flag specifies a comma-separated list of names of
+// additional known formatting functions or methods. (This legacy flag
+// is rarely used due to the automatic inference described above.)
+//
+// If the name contains a period, it must denote a specific function
+// using one of the following forms:
//
// dir/pkg.Function
// dir/pkg.Type.Method
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdversion/stdversion.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdversion/stdversion.go
new file mode 100644
index 0000000000..75d8697759
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdversion/stdversion.go
@@ -0,0 +1,159 @@
+// Copyright 2024 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 stdversion reports uses of standard library symbols that are
+// "too new" for the Go version in force in the referring file.
+package stdversion
+
+import (
+ "go/ast"
+ "go/build"
+ "go/types"
+ "regexp"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+ "golang.org/x/tools/internal/typesinternal"
+ "golang.org/x/tools/internal/versions"
+)
+
+const Doc = `report uses of too-new standard library symbols
+
+The stdversion analyzer reports references to symbols in the standard
+library that were introduced by a Go release higher than the one in
+force in the referring file. (Recall that the file's Go version is
+defined by the 'go' directive its module's go.mod file, or by a
+"//go:build go1.X" build tag at the top of the file.)
+
+The analyzer does not report a diagnostic for a reference to a "too
+new" field or method of a type that is itself "too new", as this may
+have false positives, for example if fields or methods are accessed
+through a type alias that is guarded by a Go version constraint.
+`
+
+var Analyzer = &analysis.Analyzer{
+ Name: "stdversion",
+ Doc: Doc,
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdversion",
+ RunDespiteErrors: true,
+ Run: run,
+}
+
+func run(pass *analysis.Pass) (any, error) {
+ // Prior to go1.22, versions.FileVersion returns only the
+ // toolchain version, which is of no use to us, so
+ // disable this analyzer on earlier versions.
+ if !slicesContains(build.Default.ReleaseTags, "go1.22") {
+ return nil, nil
+ }
+
+ // Don't report diagnostics for modules marked before go1.21,
+ // since at that time the go directive wasn't clearly
+ // specified as a toolchain requirement.
+ //
+ // TODO(adonovan): after go1.21, call GoVersion directly.
+ pkgVersion := any(pass.Pkg).(interface{ GoVersion() string }).GoVersion()
+ if !versions.AtLeast(pkgVersion, "go1.21") {
+ return nil, nil
+ }
+
+ // disallowedSymbols returns the set of standard library symbols
+ // in a given package that are disallowed at the specified Go version.
+ type key struct {
+ pkg *types.Package
+ version string
+ }
+ memo := make(map[key]map[types.Object]string) // records symbol's minimum Go version
+ disallowedSymbols := func(pkg *types.Package, version string) map[types.Object]string {
+ k := key{pkg, version}
+ disallowed, ok := memo[k]
+ if !ok {
+ disallowed = typesinternal.TooNewStdSymbols(pkg, version)
+ memo[k] = disallowed
+ }
+ return disallowed
+ }
+
+ // Scan the syntax looking for references to symbols
+ // that are disallowed by the version of the file.
+ inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+ nodeFilter := []ast.Node{
+ (*ast.File)(nil),
+ (*ast.Ident)(nil),
+ }
+ var fileVersion string // "" => no check
+ inspect.Preorder(nodeFilter, func(n ast.Node) {
+ switch n := n.(type) {
+ case *ast.File:
+ if isGenerated(n) {
+ // Suppress diagnostics in generated files (such as cgo).
+ fileVersion = ""
+ } else {
+ fileVersion = versions.Lang(versions.FileVersion(pass.TypesInfo, n))
+ // (may be "" if unknown)
+ }
+
+ case *ast.Ident:
+ if fileVersion != "" {
+ if obj, ok := pass.TypesInfo.Uses[n]; ok && obj.Pkg() != nil {
+ disallowed := disallowedSymbols(obj.Pkg(), fileVersion)
+ if minVersion, ok := disallowed[origin(obj)]; ok {
+ noun := "module"
+ if fileVersion != pkgVersion {
+ noun = "file"
+ }
+ pass.ReportRangef(n, "%s.%s requires %v or later (%s is %s)",
+ obj.Pkg().Name(), obj.Name(), minVersion, noun, fileVersion)
+ }
+ }
+ }
+ }
+ })
+ return nil, nil
+}
+
+// Reduced from x/tools/gopls/internal/golang/util.go. Good enough for now.
+// TODO(adonovan): use ast.IsGenerated in go1.21.
+func isGenerated(f *ast.File) bool {
+ for _, group := range f.Comments {
+ for _, comment := range group.List {
+ if matched := generatedRx.MatchString(comment.Text); matched {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+// Matches cgo generated comment as well as the proposed standard:
+//
+// https://golang.org/s/generatedcode
+var generatedRx = regexp.MustCompile(`// .*DO NOT EDIT\.?`)
+
+// origin returns the original uninstantiated symbol for obj.
+func origin(obj types.Object) types.Object {
+ switch obj := obj.(type) {
+ case *types.Var:
+ return obj.Origin()
+ case *types.Func:
+ return obj.Origin()
+ case *types.TypeName:
+ if named, ok := obj.Type().(*types.Named); ok { // (don't unalias)
+ return named.Origin().Obj()
+ }
+ }
+ return obj
+}
+
+// TODO(adonovan): use go1.21 slices.Contains.
+func slicesContains[S ~[]E, E comparable](slice S, x E) bool {
+ for _, elem := range slice {
+ if elem == x {
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go
index 16a4b3e551..c77182daef 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go
@@ -59,14 +59,13 @@ func describe(typ, inType types.Type, inName string) string {
return name
}
-func typeName(typ types.Type) string {
- typ = aliases.Unalias(typ)
- // TODO(adonovan): don't discard alias type, return its name.
- if v, _ := typ.(*types.Basic); v != nil {
- return v.Name()
- }
- if v, _ := typ.(interface{ Obj() *types.TypeName }); v != nil { // Named, TypeParam
- return v.Obj().Name()
+func typeName(t types.Type) string {
+ type hasTypeName interface{ Obj() *types.TypeName } // Alias, Named, TypeParam
+ switch t := t.(type) {
+ case *types.Basic:
+ return t.Name()
+ case hasTypeName:
+ return t.Obj().Name()
}
return ""
}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go
index 39d0d9e429..f5e760ca26 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go
@@ -447,6 +447,18 @@ func checkExampleName(pass *analysis.Pass, fn *ast.FuncDecl) {
}
}
+type tokenRange struct {
+ p, e token.Pos
+}
+
+func (r tokenRange) Pos() token.Pos {
+ return r.p
+}
+
+func (r tokenRange) End() token.Pos {
+ return r.e
+}
+
func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) {
// Want functions with 0 results and 1 parameter.
if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
@@ -464,12 +476,11 @@ func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) {
if tparams := fn.Type.TypeParams; tparams != nil && len(tparams.List) > 0 {
// Note: cmd/go/internal/load also errors about TestXXX and BenchmarkXXX functions with type parameters.
// We have currently decided to also warn before compilation/package loading. This can help users in IDEs.
- // TODO(adonovan): use ReportRangef(tparams).
- pass.Reportf(fn.Pos(), "%s has type parameters: it will not be run by go test as a %sXXX function", fn.Name.Name, prefix)
+ at := tokenRange{tparams.Opening, tparams.Closing}
+ pass.ReportRangef(at, "%s has type parameters: it will not be run by go test as a %sXXX function", fn.Name.Name, prefix)
}
if !isTestSuffix(fn.Name.Name[len(prefix):]) {
- // TODO(adonovan): use ReportRangef(fn.Name).
- pass.Reportf(fn.Pos(), "%s has malformed name: first letter after '%s' must not be lowercase", fn.Name.Name, prefix)
+ pass.ReportRangef(fn.Name, "%s has malformed name: first letter after '%s' must not be lowercase", fn.Name.Name, prefix)
}
}