mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd: update x/tools to 59ff18c
$ go get golang.org/x/tools@59ff18c $ GOWORK=off go mod tidy $ GOWORK=off go mod vendor This implies golang.org/x/sys@v0.38.0, for which I have also updated src/go.mod for consistency. I also upgraded x/mod@3f03020 to bring in some fixes to code that go vet would otherwise have flagged in this CL. This brings in a number of fixes and improvements to the analysis tools within cmd/fix, which I will apply to std and cmd presently. For golang/go#71859 Change-Id: I56c49e7ab28eb6ba55408a3721e9a898ee3067a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/719760 Auto-Submit: Alan Donovan <adonovan@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
50128a2154
commit
410ef44f00
136 changed files with 3430 additions and 1509 deletions
|
|
@ -6,12 +6,12 @@ require (
|
||||||
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5
|
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5
|
||||||
golang.org/x/arch v0.22.1-0.20251016010524-fea4a9ec4938
|
golang.org/x/arch v0.22.1-0.20251016010524-fea4a9ec4938
|
||||||
golang.org/x/build v0.0.0-20250806225920-b7c66c047964
|
golang.org/x/build v0.0.0-20250806225920-b7c66c047964
|
||||||
golang.org/x/mod v0.29.0
|
golang.org/x/mod v0.30.1-0.20251114215501-3f03020ad526
|
||||||
golang.org/x/sync v0.17.0
|
golang.org/x/sync v0.18.0
|
||||||
golang.org/x/sys v0.37.0
|
golang.org/x/sys v0.38.0
|
||||||
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8
|
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54
|
||||||
golang.org/x/term v0.34.0
|
golang.org/x/term v0.34.0
|
||||||
golang.org/x/tools v0.38.1-0.20251015192825-7d9453ccc0f5
|
golang.org/x/tools v0.39.1-0.20251114194111-59ff18ce4883
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|
|
||||||
|
|
@ -10,19 +10,19 @@ golang.org/x/arch v0.22.1-0.20251016010524-fea4a9ec4938 h1:VJ182b/ajNehMFRltVfCh
|
||||||
golang.org/x/arch v0.22.1-0.20251016010524-fea4a9ec4938/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
golang.org/x/arch v0.22.1-0.20251016010524-fea4a9ec4938/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||||
golang.org/x/build v0.0.0-20250806225920-b7c66c047964 h1:yRs1K51GKq7hsIO+YHJ8LsslrvwFceNPIv0tYjpcBd0=
|
golang.org/x/build v0.0.0-20250806225920-b7c66c047964 h1:yRs1K51GKq7hsIO+YHJ8LsslrvwFceNPIv0tYjpcBd0=
|
||||||
golang.org/x/build v0.0.0-20250806225920-b7c66c047964/go.mod h1:i9Vx7+aOQUpYJRxSO+OpRStVBCVL/9ccI51xblWm5WY=
|
golang.org/x/build v0.0.0-20250806225920-b7c66c047964/go.mod h1:i9Vx7+aOQUpYJRxSO+OpRStVBCVL/9ccI51xblWm5WY=
|
||||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
golang.org/x/mod v0.30.1-0.20251114215501-3f03020ad526 h1:LPpBM4CGUFMC47OqgAr2YIUxEUjH1Ur+D3KR/1LiuuQ=
|
||||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
golang.org/x/mod v0.30.1-0.20251114215501-3f03020ad526/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
|
||||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU=
|
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 h1:E2/AqCUMZGgd73TQkxUMcMla25GB9i/5HOdLr+uH7Vo=
|
||||||
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
|
golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ=
|
||||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||||
golang.org/x/tools v0.38.1-0.20251015192825-7d9453ccc0f5 h1:cz7f45KGWAtyIrz6bm45Gc+lw8beIxBSW3EQh4Bwbg4=
|
golang.org/x/tools v0.39.1-0.20251114194111-59ff18ce4883 h1:aeO0AW8d+a+5+hNQx9f4J5egD89zftrY2x42KGQjLzI=
|
||||||
golang.org/x/tools v0.38.1-0.20251015192825-7d9453ccc0f5/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
golang.org/x/tools v0.39.1-0.20251114194111-59ff18ce4883/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
|
||||||
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef h1:mqLYrXCXYEZOop9/Dbo6RPX11539nwiCNBb1icVPmw8=
|
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef h1:mqLYrXCXYEZOop9/Dbo6RPX11539nwiCNBb1icVPmw8=
|
||||||
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef/go.mod h1:8xcPgWmwlZONN1D9bjxtHEjrUtSEa3fakVF8iaewYKQ=
|
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef/go.mod h1:8xcPgWmwlZONN1D9bjxtHEjrUtSEa3fakVF8iaewYKQ=
|
||||||
|
|
|
||||||
2
src/cmd/vendor/golang.org/x/mod/modfile/print.go
generated
vendored
2
src/cmd/vendor/golang.org/x/mod/modfile/print.go
generated
vendored
|
|
@ -33,7 +33,7 @@ type printer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf prints to the buffer.
|
// printf prints to the buffer.
|
||||||
func (p *printer) printf(format string, args ...interface{}) {
|
func (p *printer) printf(format string, args ...any) {
|
||||||
fmt.Fprintf(p, format, args...)
|
fmt.Fprintf(p, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/mod/modfile/read.go
generated
vendored
4
src/cmd/vendor/golang.org/x/mod/modfile/read.go
generated
vendored
|
|
@ -94,7 +94,7 @@ func (x *FileSyntax) Span() (start, end Position) {
|
||||||
// line, the new line is added at the end of the block containing hint,
|
// line, the new line is added at the end of the block containing hint,
|
||||||
// extracting hint into a new block if it is not yet in one.
|
// extracting hint into a new block if it is not yet in one.
|
||||||
//
|
//
|
||||||
// If the hint is non-nil buts its first token does not match,
|
// If the hint is non-nil but its first token does not match,
|
||||||
// the new line is added after the block containing hint
|
// the new line is added after the block containing hint
|
||||||
// (or hint itself, if not in a block).
|
// (or hint itself, if not in a block).
|
||||||
//
|
//
|
||||||
|
|
@ -600,7 +600,7 @@ func (in *input) readToken() {
|
||||||
|
|
||||||
// Checked all punctuation. Must be identifier token.
|
// Checked all punctuation. Must be identifier token.
|
||||||
if c := in.peekRune(); !isIdent(c) {
|
if c := in.peekRune(); !isIdent(c) {
|
||||||
in.Error(fmt.Sprintf("unexpected input character %#q", c))
|
in.Error(fmt.Sprintf("unexpected input character %#q", rune(c)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan over identifier.
|
// Scan over identifier.
|
||||||
|
|
|
||||||
8
src/cmd/vendor/golang.org/x/mod/modfile/rule.go
generated
vendored
8
src/cmd/vendor/golang.org/x/mod/modfile/rule.go
generated
vendored
|
|
@ -368,7 +368,7 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a
|
||||||
Err: err,
|
Err: err,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
errorf := func(format string, args ...interface{}) {
|
errorf := func(format string, args ...any) {
|
||||||
wrapError(fmt.Errorf(format, args...))
|
wrapError(fmt.Errorf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -574,7 +574,7 @@ func parseReplace(filename string, line *Line, verb string, args []string, fix V
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errorf := func(format string, args ...interface{}) *Error {
|
errorf := func(format string, args ...any) *Error {
|
||||||
return wrapError(fmt.Errorf(format, args...))
|
return wrapError(fmt.Errorf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -685,7 +685,7 @@ func (f *WorkFile) add(errs *ErrorList, line *Line, verb string, args []string,
|
||||||
Err: err,
|
Err: err,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
errorf := func(format string, args ...interface{}) {
|
errorf := func(format string, args ...any) {
|
||||||
wrapError(fmt.Errorf(format, args...))
|
wrapError(fmt.Errorf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1594,7 +1594,7 @@ func (f *File) AddRetract(vi VersionInterval, rationale string) error {
|
||||||
r.Syntax = f.Syntax.addLine(nil, "retract", "[", AutoQuote(vi.Low), ",", AutoQuote(vi.High), "]")
|
r.Syntax = f.Syntax.addLine(nil, "retract", "[", AutoQuote(vi.Low), ",", AutoQuote(vi.High), "]")
|
||||||
}
|
}
|
||||||
if rationale != "" {
|
if rationale != "" {
|
||||||
for _, line := range strings.Split(rationale, "\n") {
|
for line := range strings.SplitSeq(rationale, "\n") {
|
||||||
com := Comment{Token: "// " + line}
|
com := Comment{Token: "// " + line}
|
||||||
r.Syntax.Comment().Before = append(r.Syntax.Comment().Before, com)
|
r.Syntax.Comment().Before = append(r.Syntax.Comment().Before, com)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/mod/module/module.go
generated
vendored
6
src/cmd/vendor/golang.org/x/mod/module/module.go
generated
vendored
|
|
@ -261,7 +261,7 @@ func modPathOK(r rune) bool {
|
||||||
|
|
||||||
// importPathOK reports whether r can appear in a package import path element.
|
// importPathOK reports whether r can appear in a package import path element.
|
||||||
//
|
//
|
||||||
// Import paths are intermediate between module paths and file paths: we allow
|
// Import paths are intermediate between module paths and file paths: we
|
||||||
// disallow characters that would be confusing or ambiguous as arguments to
|
// disallow characters that would be confusing or ambiguous as arguments to
|
||||||
// 'go get' (such as '@' and ' ' ), but allow certain characters that are
|
// 'go get' (such as '@' and ' ' ), but allow certain characters that are
|
||||||
// otherwise-unambiguous on the command line and historically used for some
|
// otherwise-unambiguous on the command line and historically used for some
|
||||||
|
|
@ -802,8 +802,8 @@ func MatchPrefixPatterns(globs, target string) bool {
|
||||||
for globs != "" {
|
for globs != "" {
|
||||||
// Extract next non-empty glob in comma-separated list.
|
// Extract next non-empty glob in comma-separated list.
|
||||||
var glob string
|
var glob string
|
||||||
if i := strings.Index(globs, ","); i >= 0 {
|
if before, after, ok := strings.Cut(globs, ","); ok {
|
||||||
glob, globs = globs[:i], globs[i+1:]
|
glob, globs = before, after
|
||||||
} else {
|
} else {
|
||||||
glob, globs = globs, ""
|
glob, globs = globs, ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/mod/semver/semver.go
generated
vendored
4
src/cmd/vendor/golang.org/x/mod/semver/semver.go
generated
vendored
|
|
@ -45,8 +45,8 @@ func IsValid(v string) bool {
|
||||||
|
|
||||||
// Canonical returns the canonical formatting of the semantic version v.
|
// Canonical returns the canonical formatting of the semantic version v.
|
||||||
// It fills in any missing .MINOR or .PATCH and discards build metadata.
|
// It fills in any missing .MINOR or .PATCH and discards build metadata.
|
||||||
// Two semantic versions compare equal only if their canonical formattings
|
// Two semantic versions compare equal only if their canonical formatting
|
||||||
// are identical strings.
|
// is an identical string.
|
||||||
// The canonical invalid semantic version is the empty string.
|
// The canonical invalid semantic version is the empty string.
|
||||||
func Canonical(v string) string {
|
func Canonical(v string) string {
|
||||||
p, ok := parse(v)
|
p, ok := parse(v)
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/mod/sumdb/cache.go
generated
vendored
6
src/cmd/vendor/golang.org/x/mod/sumdb/cache.go
generated
vendored
|
|
@ -20,13 +20,13 @@ type parCache struct {
|
||||||
type cacheEntry struct {
|
type cacheEntry struct {
|
||||||
done uint32
|
done uint32
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
result interface{}
|
result any
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do calls the function f if and only if Do is being called for the first time with this key.
|
// Do calls the function f if and only if Do is being called for the first time with this key.
|
||||||
// No call to Do with a given key returns until the one call to f returns.
|
// No call to Do with a given key returns until the one call to f returns.
|
||||||
// Do returns the value returned by the one call to f.
|
// Do returns the value returned by the one call to f.
|
||||||
func (c *parCache) Do(key interface{}, f func() interface{}) interface{} {
|
func (c *parCache) Do(key any, f func() any) any {
|
||||||
entryIface, ok := c.m.Load(key)
|
entryIface, ok := c.m.Load(key)
|
||||||
if !ok {
|
if !ok {
|
||||||
entryIface, _ = c.m.LoadOrStore(key, new(cacheEntry))
|
entryIface, _ = c.m.LoadOrStore(key, new(cacheEntry))
|
||||||
|
|
@ -46,7 +46,7 @@ func (c *parCache) Do(key interface{}, f func() interface{}) interface{} {
|
||||||
// Get returns the cached result associated with key.
|
// Get returns the cached result associated with key.
|
||||||
// It returns nil if there is no such result.
|
// It returns nil if there is no such result.
|
||||||
// If the result for key is being computed, Get does not wait for the computation to finish.
|
// If the result for key is being computed, Get does not wait for the computation to finish.
|
||||||
func (c *parCache) Get(key interface{}) interface{} {
|
func (c *parCache) Get(key any) any {
|
||||||
entryIface, ok := c.m.Load(key)
|
entryIface, ok := c.m.Load(key)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/mod/sumdb/client.go
generated
vendored
6
src/cmd/vendor/golang.org/x/mod/sumdb/client.go
generated
vendored
|
|
@ -244,7 +244,7 @@ func (c *Client) Lookup(path, vers string) (lines []string, err error) {
|
||||||
data []byte
|
data []byte
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
result := c.record.Do(file, func() interface{} {
|
result := c.record.Do(file, func() any {
|
||||||
// Try the on-disk cache, or else get from web.
|
// Try the on-disk cache, or else get from web.
|
||||||
writeCache := false
|
writeCache := false
|
||||||
data, err := c.ops.ReadCache(file)
|
data, err := c.ops.ReadCache(file)
|
||||||
|
|
@ -284,7 +284,7 @@ func (c *Client) Lookup(path, vers string) (lines []string, err error) {
|
||||||
// (with or without /go.mod).
|
// (with or without /go.mod).
|
||||||
prefix := path + " " + vers + " "
|
prefix := path + " " + vers + " "
|
||||||
var hashes []string
|
var hashes []string
|
||||||
for _, line := range strings.Split(string(result.data), "\n") {
|
for line := range strings.SplitSeq(string(result.data), "\n") {
|
||||||
if strings.HasPrefix(line, prefix) {
|
if strings.HasPrefix(line, prefix) {
|
||||||
hashes = append(hashes, line)
|
hashes = append(hashes, line)
|
||||||
}
|
}
|
||||||
|
|
@ -552,7 +552,7 @@ func (c *Client) readTile(tile tlog.Tile) ([]byte, error) {
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
result := c.tileCache.Do(tile, func() interface{} {
|
result := c.tileCache.Do(tile, func() any {
|
||||||
// Try the requested tile in on-disk cache.
|
// Try the requested tile in on-disk cache.
|
||||||
data, err := c.ops.ReadCache(c.tileCacheKey(tile))
|
data, err := c.ops.ReadCache(c.tileCacheKey(tile))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
|
||||||
22
src/cmd/vendor/golang.org/x/mod/sumdb/note/note.go
generated
vendored
22
src/cmd/vendor/golang.org/x/mod/sumdb/note/note.go
generated
vendored
|
|
@ -240,8 +240,8 @@ func isValidName(name string) bool {
|
||||||
|
|
||||||
// NewVerifier construct a new [Verifier] from an encoded verifier key.
|
// NewVerifier construct a new [Verifier] from an encoded verifier key.
|
||||||
func NewVerifier(vkey string) (Verifier, error) {
|
func NewVerifier(vkey string) (Verifier, error) {
|
||||||
name, vkey := chop(vkey, "+")
|
name, vkey, _ := strings.Cut(vkey, "+")
|
||||||
hash16, key64 := chop(vkey, "+")
|
hash16, key64, _ := strings.Cut(vkey, "+")
|
||||||
hash, err1 := strconv.ParseUint(hash16, 16, 32)
|
hash, err1 := strconv.ParseUint(hash16, 16, 32)
|
||||||
key, err2 := base64.StdEncoding.DecodeString(key64)
|
key, err2 := base64.StdEncoding.DecodeString(key64)
|
||||||
if len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
|
if len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
|
||||||
|
|
@ -276,12 +276,8 @@ func NewVerifier(vkey string) (Verifier, error) {
|
||||||
// chop chops s at the first instance of sep, if any,
|
// chop chops s at the first instance of sep, if any,
|
||||||
// and returns the text before and after sep.
|
// and returns the text before and after sep.
|
||||||
// If sep is not present, chop returns before is s and after is empty.
|
// If sep is not present, chop returns before is s and after is empty.
|
||||||
func chop(s, sep string) (before, after string) {
|
func chop(s, sep string) (before, after string, ok bool) {
|
||||||
i := strings.Index(s, sep)
|
return strings.Cut(s, sep)
|
||||||
if i < 0 {
|
|
||||||
return s, ""
|
|
||||||
}
|
|
||||||
return s[:i], s[i+len(sep):]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifier is a trivial Verifier implementation.
|
// verifier is a trivial Verifier implementation.
|
||||||
|
|
@ -297,10 +293,10 @@ func (v *verifier) Verify(msg, sig []byte) bool { return v.verify(msg, sig) }
|
||||||
|
|
||||||
// NewSigner constructs a new [Signer] from an encoded signer key.
|
// NewSigner constructs a new [Signer] from an encoded signer key.
|
||||||
func NewSigner(skey string) (Signer, error) {
|
func NewSigner(skey string) (Signer, error) {
|
||||||
priv1, skey := chop(skey, "+")
|
priv1, skey, _ := strings.Cut(skey, "+")
|
||||||
priv2, skey := chop(skey, "+")
|
priv2, skey, _ := strings.Cut(skey, "+")
|
||||||
name, skey := chop(skey, "+")
|
name, skey, _ := strings.Cut(skey, "+")
|
||||||
hash16, key64 := chop(skey, "+")
|
hash16, key64, _ := strings.Cut(skey, "+")
|
||||||
hash, err1 := strconv.ParseUint(hash16, 16, 32)
|
hash, err1 := strconv.ParseUint(hash16, 16, 32)
|
||||||
key, err2 := base64.StdEncoding.DecodeString(key64)
|
key, err2 := base64.StdEncoding.DecodeString(key64)
|
||||||
if priv1 != "PRIVATE" || priv2 != "KEY" || len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
|
if priv1 != "PRIVATE" || priv2 != "KEY" || len(hash16) != 8 || err1 != nil || err2 != nil || !isValidName(name) || len(key) == 0 {
|
||||||
|
|
@ -557,7 +553,7 @@ func Open(msg []byte, known Verifiers) (*Note, error) {
|
||||||
return nil, errMalformedNote
|
return nil, errMalformedNote
|
||||||
}
|
}
|
||||||
line = line[len(sigPrefix):]
|
line = line[len(sigPrefix):]
|
||||||
name, b64 := chop(string(line), " ")
|
name, b64, _ := chop(string(line), " ")
|
||||||
sig, err := base64.StdEncoding.DecodeString(b64)
|
sig, err := base64.StdEncoding.DecodeString(b64)
|
||||||
if err != nil || !isValidName(name) || b64 == "" || len(sig) < 5 {
|
if err != nil || !isValidName(name) || b64 == "" || len(sig) < 5 {
|
||||||
return nil, errMalformedNote
|
return nil, errMalformedNote
|
||||||
|
|
|
||||||
3
src/cmd/vendor/golang.org/x/mod/sumdb/server.go
generated
vendored
3
src/cmd/vendor/golang.org/x/mod/sumdb/server.go
generated
vendored
|
|
@ -76,8 +76,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, "invalid module@version syntax", http.StatusBadRequest)
|
http.Error(w, "invalid module@version syntax", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
i := strings.Index(mod, "@")
|
escPath, escVers, _ := strings.Cut(mod, "@")
|
||||||
escPath, escVers := mod[:i], mod[i+1:]
|
|
||||||
path, err := module.UnescapePath(escPath)
|
path, err := module.UnescapePath(escPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reportError(w, err)
|
reportError(w, err)
|
||||||
|
|
|
||||||
2
src/cmd/vendor/golang.org/x/mod/sumdb/test.go
generated
vendored
2
src/cmd/vendor/golang.org/x/mod/sumdb/test.go
generated
vendored
|
|
@ -66,7 +66,7 @@ func (s *TestServer) ReadRecords(ctx context.Context, id, n int64) ([][]byte, er
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
var list [][]byte
|
var list [][]byte
|
||||||
for i := int64(0); i < n; i++ {
|
for i := range n {
|
||||||
if id+i >= int64(len(s.records)) {
|
if id+i >= int64(len(s.records)) {
|
||||||
return nil, fmt.Errorf("missing records")
|
return nil, fmt.Errorf("missing records")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/mod/sumdb/tlog/note.go
generated
vendored
4
src/cmd/vendor/golang.org/x/mod/sumdb/tlog/note.go
generated
vendored
|
|
@ -35,7 +35,7 @@ type Tree struct {
|
||||||
// A future backwards-incompatible encoding would use a different
|
// A future backwards-incompatible encoding would use a different
|
||||||
// first line (for example, "go.sum database tree v2").
|
// first line (for example, "go.sum database tree v2").
|
||||||
func FormatTree(tree Tree) []byte {
|
func FormatTree(tree Tree) []byte {
|
||||||
return []byte(fmt.Sprintf("go.sum database tree\n%d\n%s\n", tree.N, tree.Hash))
|
return fmt.Appendf(nil, "go.sum database tree\n%d\n%s\n", tree.N, tree.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
var errMalformedTree = errors.New("malformed tree note")
|
var errMalformedTree = errors.New("malformed tree note")
|
||||||
|
|
@ -87,7 +87,7 @@ func FormatRecord(id int64, text []byte) (msg []byte, err error) {
|
||||||
if !isValidRecordText(text) {
|
if !isValidRecordText(text) {
|
||||||
return nil, errMalformedRecord
|
return nil, errMalformedRecord
|
||||||
}
|
}
|
||||||
msg = []byte(fmt.Sprintf("%d\n", id))
|
msg = fmt.Appendf(nil, "%d\n", id)
|
||||||
msg = append(msg, text...)
|
msg = append(msg, text...)
|
||||||
msg = append(msg, '\n')
|
msg = append(msg, '\n')
|
||||||
return msg, nil
|
return msg, nil
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tlog.go
generated
vendored
4
src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tlog.go
generated
vendored
|
|
@ -194,7 +194,7 @@ func StoredHashesForRecordHash(n int64, h Hash, r HashReader) ([]Hash, error) {
|
||||||
// and consumes a hash from an adjacent subtree.
|
// and consumes a hash from an adjacent subtree.
|
||||||
m := int(bits.TrailingZeros64(uint64(n + 1)))
|
m := int(bits.TrailingZeros64(uint64(n + 1)))
|
||||||
indexes := make([]int64, m)
|
indexes := make([]int64, m)
|
||||||
for i := 0; i < m; i++ {
|
for i := range m {
|
||||||
// We arrange indexes in sorted order.
|
// We arrange indexes in sorted order.
|
||||||
// Note that n>>i is always odd.
|
// Note that n>>i is always odd.
|
||||||
indexes[m-1-i] = StoredHashIndex(i, n>>uint(i)-1)
|
indexes[m-1-i] = StoredHashIndex(i, n>>uint(i)-1)
|
||||||
|
|
@ -210,7 +210,7 @@ func StoredHashesForRecordHash(n int64, h Hash, r HashReader) ([]Hash, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build new hashes.
|
// Build new hashes.
|
||||||
for i := 0; i < m; i++ {
|
for i := range m {
|
||||||
h = NodeHash(old[m-1-i], h)
|
h = NodeHash(old[m-1-i], h)
|
||||||
hashes = append(hashes, h)
|
hashes = append(hashes, h)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
src/cmd/vendor/golang.org/x/mod/zip/zip.go
generated
vendored
2
src/cmd/vendor/golang.org/x/mod/zip/zip.go
generated
vendored
|
|
@ -780,7 +780,7 @@ func (fi dataFileInfo) Size() int64 { return int64(len(fi.f.data)) }
|
||||||
func (fi dataFileInfo) Mode() os.FileMode { return 0644 }
|
func (fi dataFileInfo) Mode() os.FileMode { return 0644 }
|
||||||
func (fi dataFileInfo) ModTime() time.Time { return time.Time{} }
|
func (fi dataFileInfo) ModTime() time.Time { return time.Time{} }
|
||||||
func (fi dataFileInfo) IsDir() bool { return false }
|
func (fi dataFileInfo) IsDir() bool { return false }
|
||||||
func (fi dataFileInfo) Sys() interface{} { return nil }
|
func (fi dataFileInfo) Sys() any { return nil }
|
||||||
|
|
||||||
// isVendoredPackage attempts to report whether the given filename is contained
|
// isVendoredPackage attempts to report whether the given filename is contained
|
||||||
// in a package whose import path contains (but does not end with) the component
|
// in a package whose import path contains (but does not end with) the component
|
||||||
|
|
|
||||||
2
src/cmd/vendor/golang.org/x/sync/errgroup/errgroup.go
generated
vendored
2
src/cmd/vendor/golang.org/x/sync/errgroup/errgroup.go
generated
vendored
|
|
@ -3,7 +3,7 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package errgroup provides synchronization, error propagation, and Context
|
// Package errgroup provides synchronization, error propagation, and Context
|
||||||
// cancelation for groups of goroutines working on subtasks of a common task.
|
// cancellation for groups of goroutines working on subtasks of a common task.
|
||||||
//
|
//
|
||||||
// [errgroup.Group] is related to [sync.WaitGroup] but adds handling of tasks
|
// [errgroup.Group] is related to [sync.WaitGroup] but adds handling of tasks
|
||||||
// returning errors.
|
// returning errors.
|
||||||
|
|
|
||||||
2
src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
2
src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
|
|
@ -226,6 +226,7 @@ struct ltchars {
|
||||||
#include <linux/cryptouser.h>
|
#include <linux/cryptouser.h>
|
||||||
#include <linux/devlink.h>
|
#include <linux/devlink.h>
|
||||||
#include <linux/dm-ioctl.h>
|
#include <linux/dm-ioctl.h>
|
||||||
|
#include <linux/elf.h>
|
||||||
#include <linux/errqueue.h>
|
#include <linux/errqueue.h>
|
||||||
#include <linux/ethtool_netlink.h>
|
#include <linux/ethtool_netlink.h>
|
||||||
#include <linux/falloc.h>
|
#include <linux/falloc.h>
|
||||||
|
|
@ -529,6 +530,7 @@ ccflags="$@"
|
||||||
$2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
|
$2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
|
||||||
$2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ ||
|
$2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ ||
|
||||||
$2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ ||
|
$2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ ||
|
||||||
|
$2 ~ /^(DT|EI|ELF|EV|NN|NT|PF|SHF|SHN|SHT|STB|STT|VER)_/ ||
|
||||||
$2 ~ /^O?XTABS$/ ||
|
$2 ~ /^O?XTABS$/ ||
|
||||||
$2 ~ /^TC[IO](ON|OFF)$/ ||
|
$2 ~ /^TC[IO](ON|OFF)$/ ||
|
||||||
$2 ~ /^IN_/ ||
|
$2 ~ /^IN_/ ||
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
6
src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
|
|
@ -2643,3 +2643,9 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) {
|
||||||
|
|
||||||
//sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error)
|
//sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error)
|
||||||
//sys Mseal(b []byte, flags uint) (err error)
|
//sys Mseal(b []byte, flags uint) (err error)
|
||||||
|
|
||||||
|
//sys setMemPolicy(mode int, mask *CPUSet, size int) (err error) = SYS_SET_MEMPOLICY
|
||||||
|
|
||||||
|
func SetMemPolicy(mode int, mask *CPUSet) error {
|
||||||
|
return setMemPolicy(mode, mask, _CPU_SETSIZE)
|
||||||
|
}
|
||||||
|
|
|
||||||
359
src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go
generated
vendored
359
src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go
generated
vendored
|
|
@ -853,20 +853,86 @@ const (
|
||||||
DM_VERSION_MAJOR = 0x4
|
DM_VERSION_MAJOR = 0x4
|
||||||
DM_VERSION_MINOR = 0x32
|
DM_VERSION_MINOR = 0x32
|
||||||
DM_VERSION_PATCHLEVEL = 0x0
|
DM_VERSION_PATCHLEVEL = 0x0
|
||||||
|
DT_ADDRRNGHI = 0x6ffffeff
|
||||||
|
DT_ADDRRNGLO = 0x6ffffe00
|
||||||
DT_BLK = 0x6
|
DT_BLK = 0x6
|
||||||
DT_CHR = 0x2
|
DT_CHR = 0x2
|
||||||
|
DT_DEBUG = 0x15
|
||||||
DT_DIR = 0x4
|
DT_DIR = 0x4
|
||||||
|
DT_ENCODING = 0x20
|
||||||
DT_FIFO = 0x1
|
DT_FIFO = 0x1
|
||||||
|
DT_FINI = 0xd
|
||||||
|
DT_FLAGS_1 = 0x6ffffffb
|
||||||
|
DT_GNU_HASH = 0x6ffffef5
|
||||||
|
DT_HASH = 0x4
|
||||||
|
DT_HIOS = 0x6ffff000
|
||||||
|
DT_HIPROC = 0x7fffffff
|
||||||
|
DT_INIT = 0xc
|
||||||
|
DT_JMPREL = 0x17
|
||||||
DT_LNK = 0xa
|
DT_LNK = 0xa
|
||||||
|
DT_LOOS = 0x6000000d
|
||||||
|
DT_LOPROC = 0x70000000
|
||||||
|
DT_NEEDED = 0x1
|
||||||
|
DT_NULL = 0x0
|
||||||
|
DT_PLTGOT = 0x3
|
||||||
|
DT_PLTREL = 0x14
|
||||||
|
DT_PLTRELSZ = 0x2
|
||||||
DT_REG = 0x8
|
DT_REG = 0x8
|
||||||
|
DT_REL = 0x11
|
||||||
|
DT_RELA = 0x7
|
||||||
|
DT_RELACOUNT = 0x6ffffff9
|
||||||
|
DT_RELAENT = 0x9
|
||||||
|
DT_RELASZ = 0x8
|
||||||
|
DT_RELCOUNT = 0x6ffffffa
|
||||||
|
DT_RELENT = 0x13
|
||||||
|
DT_RELSZ = 0x12
|
||||||
|
DT_RPATH = 0xf
|
||||||
DT_SOCK = 0xc
|
DT_SOCK = 0xc
|
||||||
|
DT_SONAME = 0xe
|
||||||
|
DT_STRSZ = 0xa
|
||||||
|
DT_STRTAB = 0x5
|
||||||
|
DT_SYMBOLIC = 0x10
|
||||||
|
DT_SYMENT = 0xb
|
||||||
|
DT_SYMTAB = 0x6
|
||||||
|
DT_TEXTREL = 0x16
|
||||||
DT_UNKNOWN = 0x0
|
DT_UNKNOWN = 0x0
|
||||||
|
DT_VALRNGHI = 0x6ffffdff
|
||||||
|
DT_VALRNGLO = 0x6ffffd00
|
||||||
|
DT_VERDEF = 0x6ffffffc
|
||||||
|
DT_VERDEFNUM = 0x6ffffffd
|
||||||
|
DT_VERNEED = 0x6ffffffe
|
||||||
|
DT_VERNEEDNUM = 0x6fffffff
|
||||||
|
DT_VERSYM = 0x6ffffff0
|
||||||
DT_WHT = 0xe
|
DT_WHT = 0xe
|
||||||
ECHO = 0x8
|
ECHO = 0x8
|
||||||
ECRYPTFS_SUPER_MAGIC = 0xf15f
|
ECRYPTFS_SUPER_MAGIC = 0xf15f
|
||||||
EFD_SEMAPHORE = 0x1
|
EFD_SEMAPHORE = 0x1
|
||||||
EFIVARFS_MAGIC = 0xde5e81e4
|
EFIVARFS_MAGIC = 0xde5e81e4
|
||||||
EFS_SUPER_MAGIC = 0x414a53
|
EFS_SUPER_MAGIC = 0x414a53
|
||||||
|
EI_CLASS = 0x4
|
||||||
|
EI_DATA = 0x5
|
||||||
|
EI_MAG0 = 0x0
|
||||||
|
EI_MAG1 = 0x1
|
||||||
|
EI_MAG2 = 0x2
|
||||||
|
EI_MAG3 = 0x3
|
||||||
|
EI_NIDENT = 0x10
|
||||||
|
EI_OSABI = 0x7
|
||||||
|
EI_PAD = 0x8
|
||||||
|
EI_VERSION = 0x6
|
||||||
|
ELFCLASS32 = 0x1
|
||||||
|
ELFCLASS64 = 0x2
|
||||||
|
ELFCLASSNONE = 0x0
|
||||||
|
ELFCLASSNUM = 0x3
|
||||||
|
ELFDATA2LSB = 0x1
|
||||||
|
ELFDATA2MSB = 0x2
|
||||||
|
ELFDATANONE = 0x0
|
||||||
|
ELFMAG = "\177ELF"
|
||||||
|
ELFMAG0 = 0x7f
|
||||||
|
ELFMAG1 = 'E'
|
||||||
|
ELFMAG2 = 'L'
|
||||||
|
ELFMAG3 = 'F'
|
||||||
|
ELFOSABI_LINUX = 0x3
|
||||||
|
ELFOSABI_NONE = 0x0
|
||||||
EM_386 = 0x3
|
EM_386 = 0x3
|
||||||
EM_486 = 0x6
|
EM_486 = 0x6
|
||||||
EM_68K = 0x4
|
EM_68K = 0x4
|
||||||
|
|
@ -1152,14 +1218,24 @@ const (
|
||||||
ETH_P_WCCP = 0x883e
|
ETH_P_WCCP = 0x883e
|
||||||
ETH_P_X25 = 0x805
|
ETH_P_X25 = 0x805
|
||||||
ETH_P_XDSA = 0xf8
|
ETH_P_XDSA = 0xf8
|
||||||
|
ET_CORE = 0x4
|
||||||
|
ET_DYN = 0x3
|
||||||
|
ET_EXEC = 0x2
|
||||||
|
ET_HIPROC = 0xffff
|
||||||
|
ET_LOPROC = 0xff00
|
||||||
|
ET_NONE = 0x0
|
||||||
|
ET_REL = 0x1
|
||||||
EV_ABS = 0x3
|
EV_ABS = 0x3
|
||||||
EV_CNT = 0x20
|
EV_CNT = 0x20
|
||||||
|
EV_CURRENT = 0x1
|
||||||
EV_FF = 0x15
|
EV_FF = 0x15
|
||||||
EV_FF_STATUS = 0x17
|
EV_FF_STATUS = 0x17
|
||||||
EV_KEY = 0x1
|
EV_KEY = 0x1
|
||||||
EV_LED = 0x11
|
EV_LED = 0x11
|
||||||
EV_MAX = 0x1f
|
EV_MAX = 0x1f
|
||||||
EV_MSC = 0x4
|
EV_MSC = 0x4
|
||||||
|
EV_NONE = 0x0
|
||||||
|
EV_NUM = 0x2
|
||||||
EV_PWR = 0x16
|
EV_PWR = 0x16
|
||||||
EV_REL = 0x2
|
EV_REL = 0x2
|
||||||
EV_REP = 0x14
|
EV_REP = 0x14
|
||||||
|
|
@ -2276,7 +2352,167 @@ const (
|
||||||
NLM_F_REPLACE = 0x100
|
NLM_F_REPLACE = 0x100
|
||||||
NLM_F_REQUEST = 0x1
|
NLM_F_REQUEST = 0x1
|
||||||
NLM_F_ROOT = 0x100
|
NLM_F_ROOT = 0x100
|
||||||
|
NN_386_IOPERM = "LINUX"
|
||||||
|
NN_386_TLS = "LINUX"
|
||||||
|
NN_ARC_V2 = "LINUX"
|
||||||
|
NN_ARM_FPMR = "LINUX"
|
||||||
|
NN_ARM_GCS = "LINUX"
|
||||||
|
NN_ARM_HW_BREAK = "LINUX"
|
||||||
|
NN_ARM_HW_WATCH = "LINUX"
|
||||||
|
NN_ARM_PACA_KEYS = "LINUX"
|
||||||
|
NN_ARM_PACG_KEYS = "LINUX"
|
||||||
|
NN_ARM_PAC_ENABLED_KEYS = "LINUX"
|
||||||
|
NN_ARM_PAC_MASK = "LINUX"
|
||||||
|
NN_ARM_POE = "LINUX"
|
||||||
|
NN_ARM_SSVE = "LINUX"
|
||||||
|
NN_ARM_SVE = "LINUX"
|
||||||
|
NN_ARM_SYSTEM_CALL = "LINUX"
|
||||||
|
NN_ARM_TAGGED_ADDR_CTRL = "LINUX"
|
||||||
|
NN_ARM_TLS = "LINUX"
|
||||||
|
NN_ARM_VFP = "LINUX"
|
||||||
|
NN_ARM_ZA = "LINUX"
|
||||||
|
NN_ARM_ZT = "LINUX"
|
||||||
|
NN_AUXV = "CORE"
|
||||||
|
NN_FILE = "CORE"
|
||||||
|
NN_GNU_PROPERTY_TYPE_0 = "GNU"
|
||||||
|
NN_LOONGARCH_CPUCFG = "LINUX"
|
||||||
|
NN_LOONGARCH_CSR = "LINUX"
|
||||||
|
NN_LOONGARCH_HW_BREAK = "LINUX"
|
||||||
|
NN_LOONGARCH_HW_WATCH = "LINUX"
|
||||||
|
NN_LOONGARCH_LASX = "LINUX"
|
||||||
|
NN_LOONGARCH_LBT = "LINUX"
|
||||||
|
NN_LOONGARCH_LSX = "LINUX"
|
||||||
|
NN_MIPS_DSP = "LINUX"
|
||||||
|
NN_MIPS_FP_MODE = "LINUX"
|
||||||
|
NN_MIPS_MSA = "LINUX"
|
||||||
|
NN_PPC_DEXCR = "LINUX"
|
||||||
|
NN_PPC_DSCR = "LINUX"
|
||||||
|
NN_PPC_EBB = "LINUX"
|
||||||
|
NN_PPC_HASHKEYR = "LINUX"
|
||||||
|
NN_PPC_PKEY = "LINUX"
|
||||||
|
NN_PPC_PMU = "LINUX"
|
||||||
|
NN_PPC_PPR = "LINUX"
|
||||||
|
NN_PPC_SPE = "LINUX"
|
||||||
|
NN_PPC_TAR = "LINUX"
|
||||||
|
NN_PPC_TM_CDSCR = "LINUX"
|
||||||
|
NN_PPC_TM_CFPR = "LINUX"
|
||||||
|
NN_PPC_TM_CGPR = "LINUX"
|
||||||
|
NN_PPC_TM_CPPR = "LINUX"
|
||||||
|
NN_PPC_TM_CTAR = "LINUX"
|
||||||
|
NN_PPC_TM_CVMX = "LINUX"
|
||||||
|
NN_PPC_TM_CVSX = "LINUX"
|
||||||
|
NN_PPC_TM_SPR = "LINUX"
|
||||||
|
NN_PPC_VMX = "LINUX"
|
||||||
|
NN_PPC_VSX = "LINUX"
|
||||||
|
NN_PRFPREG = "CORE"
|
||||||
|
NN_PRPSINFO = "CORE"
|
||||||
|
NN_PRSTATUS = "CORE"
|
||||||
|
NN_PRXFPREG = "LINUX"
|
||||||
|
NN_RISCV_CSR = "LINUX"
|
||||||
|
NN_RISCV_TAGGED_ADDR_CTRL = "LINUX"
|
||||||
|
NN_RISCV_VECTOR = "LINUX"
|
||||||
|
NN_S390_CTRS = "LINUX"
|
||||||
|
NN_S390_GS_BC = "LINUX"
|
||||||
|
NN_S390_GS_CB = "LINUX"
|
||||||
|
NN_S390_HIGH_GPRS = "LINUX"
|
||||||
|
NN_S390_LAST_BREAK = "LINUX"
|
||||||
|
NN_S390_PREFIX = "LINUX"
|
||||||
|
NN_S390_PV_CPU_DATA = "LINUX"
|
||||||
|
NN_S390_RI_CB = "LINUX"
|
||||||
|
NN_S390_SYSTEM_CALL = "LINUX"
|
||||||
|
NN_S390_TDB = "LINUX"
|
||||||
|
NN_S390_TIMER = "LINUX"
|
||||||
|
NN_S390_TODCMP = "LINUX"
|
||||||
|
NN_S390_TODPREG = "LINUX"
|
||||||
|
NN_S390_VXRS_HIGH = "LINUX"
|
||||||
|
NN_S390_VXRS_LOW = "LINUX"
|
||||||
|
NN_SIGINFO = "CORE"
|
||||||
|
NN_TASKSTRUCT = "CORE"
|
||||||
|
NN_VMCOREDD = "LINUX"
|
||||||
|
NN_X86_SHSTK = "LINUX"
|
||||||
|
NN_X86_XSAVE_LAYOUT = "LINUX"
|
||||||
|
NN_X86_XSTATE = "LINUX"
|
||||||
NSFS_MAGIC = 0x6e736673
|
NSFS_MAGIC = 0x6e736673
|
||||||
|
NT_386_IOPERM = 0x201
|
||||||
|
NT_386_TLS = 0x200
|
||||||
|
NT_ARC_V2 = 0x600
|
||||||
|
NT_ARM_FPMR = 0x40e
|
||||||
|
NT_ARM_GCS = 0x410
|
||||||
|
NT_ARM_HW_BREAK = 0x402
|
||||||
|
NT_ARM_HW_WATCH = 0x403
|
||||||
|
NT_ARM_PACA_KEYS = 0x407
|
||||||
|
NT_ARM_PACG_KEYS = 0x408
|
||||||
|
NT_ARM_PAC_ENABLED_KEYS = 0x40a
|
||||||
|
NT_ARM_PAC_MASK = 0x406
|
||||||
|
NT_ARM_POE = 0x40f
|
||||||
|
NT_ARM_SSVE = 0x40b
|
||||||
|
NT_ARM_SVE = 0x405
|
||||||
|
NT_ARM_SYSTEM_CALL = 0x404
|
||||||
|
NT_ARM_TAGGED_ADDR_CTRL = 0x409
|
||||||
|
NT_ARM_TLS = 0x401
|
||||||
|
NT_ARM_VFP = 0x400
|
||||||
|
NT_ARM_ZA = 0x40c
|
||||||
|
NT_ARM_ZT = 0x40d
|
||||||
|
NT_AUXV = 0x6
|
||||||
|
NT_FILE = 0x46494c45
|
||||||
|
NT_GNU_PROPERTY_TYPE_0 = 0x5
|
||||||
|
NT_LOONGARCH_CPUCFG = 0xa00
|
||||||
|
NT_LOONGARCH_CSR = 0xa01
|
||||||
|
NT_LOONGARCH_HW_BREAK = 0xa05
|
||||||
|
NT_LOONGARCH_HW_WATCH = 0xa06
|
||||||
|
NT_LOONGARCH_LASX = 0xa03
|
||||||
|
NT_LOONGARCH_LBT = 0xa04
|
||||||
|
NT_LOONGARCH_LSX = 0xa02
|
||||||
|
NT_MIPS_DSP = 0x800
|
||||||
|
NT_MIPS_FP_MODE = 0x801
|
||||||
|
NT_MIPS_MSA = 0x802
|
||||||
|
NT_PPC_DEXCR = 0x111
|
||||||
|
NT_PPC_DSCR = 0x105
|
||||||
|
NT_PPC_EBB = 0x106
|
||||||
|
NT_PPC_HASHKEYR = 0x112
|
||||||
|
NT_PPC_PKEY = 0x110
|
||||||
|
NT_PPC_PMU = 0x107
|
||||||
|
NT_PPC_PPR = 0x104
|
||||||
|
NT_PPC_SPE = 0x101
|
||||||
|
NT_PPC_TAR = 0x103
|
||||||
|
NT_PPC_TM_CDSCR = 0x10f
|
||||||
|
NT_PPC_TM_CFPR = 0x109
|
||||||
|
NT_PPC_TM_CGPR = 0x108
|
||||||
|
NT_PPC_TM_CPPR = 0x10e
|
||||||
|
NT_PPC_TM_CTAR = 0x10d
|
||||||
|
NT_PPC_TM_CVMX = 0x10a
|
||||||
|
NT_PPC_TM_CVSX = 0x10b
|
||||||
|
NT_PPC_TM_SPR = 0x10c
|
||||||
|
NT_PPC_VMX = 0x100
|
||||||
|
NT_PPC_VSX = 0x102
|
||||||
|
NT_PRFPREG = 0x2
|
||||||
|
NT_PRPSINFO = 0x3
|
||||||
|
NT_PRSTATUS = 0x1
|
||||||
|
NT_PRXFPREG = 0x46e62b7f
|
||||||
|
NT_RISCV_CSR = 0x900
|
||||||
|
NT_RISCV_TAGGED_ADDR_CTRL = 0x902
|
||||||
|
NT_RISCV_VECTOR = 0x901
|
||||||
|
NT_S390_CTRS = 0x304
|
||||||
|
NT_S390_GS_BC = 0x30c
|
||||||
|
NT_S390_GS_CB = 0x30b
|
||||||
|
NT_S390_HIGH_GPRS = 0x300
|
||||||
|
NT_S390_LAST_BREAK = 0x306
|
||||||
|
NT_S390_PREFIX = 0x305
|
||||||
|
NT_S390_PV_CPU_DATA = 0x30e
|
||||||
|
NT_S390_RI_CB = 0x30d
|
||||||
|
NT_S390_SYSTEM_CALL = 0x307
|
||||||
|
NT_S390_TDB = 0x308
|
||||||
|
NT_S390_TIMER = 0x301
|
||||||
|
NT_S390_TODCMP = 0x302
|
||||||
|
NT_S390_TODPREG = 0x303
|
||||||
|
NT_S390_VXRS_HIGH = 0x30a
|
||||||
|
NT_S390_VXRS_LOW = 0x309
|
||||||
|
NT_SIGINFO = 0x53494749
|
||||||
|
NT_TASKSTRUCT = 0x4
|
||||||
|
NT_VMCOREDD = 0x700
|
||||||
|
NT_X86_SHSTK = 0x204
|
||||||
|
NT_X86_XSAVE_LAYOUT = 0x205
|
||||||
|
NT_X86_XSTATE = 0x202
|
||||||
OCFS2_SUPER_MAGIC = 0x7461636f
|
OCFS2_SUPER_MAGIC = 0x7461636f
|
||||||
OCRNL = 0x8
|
OCRNL = 0x8
|
||||||
OFDEL = 0x80
|
OFDEL = 0x80
|
||||||
|
|
@ -2463,6 +2699,59 @@ const (
|
||||||
PERF_RECORD_MISC_USER = 0x2
|
PERF_RECORD_MISC_USER = 0x2
|
||||||
PERF_SAMPLE_BRANCH_PLM_ALL = 0x7
|
PERF_SAMPLE_BRANCH_PLM_ALL = 0x7
|
||||||
PERF_SAMPLE_WEIGHT_TYPE = 0x1004000
|
PERF_SAMPLE_WEIGHT_TYPE = 0x1004000
|
||||||
|
PF_ALG = 0x26
|
||||||
|
PF_APPLETALK = 0x5
|
||||||
|
PF_ASH = 0x12
|
||||||
|
PF_ATMPVC = 0x8
|
||||||
|
PF_ATMSVC = 0x14
|
||||||
|
PF_AX25 = 0x3
|
||||||
|
PF_BLUETOOTH = 0x1f
|
||||||
|
PF_BRIDGE = 0x7
|
||||||
|
PF_CAIF = 0x25
|
||||||
|
PF_CAN = 0x1d
|
||||||
|
PF_DECnet = 0xc
|
||||||
|
PF_ECONET = 0x13
|
||||||
|
PF_FILE = 0x1
|
||||||
|
PF_IB = 0x1b
|
||||||
|
PF_IEEE802154 = 0x24
|
||||||
|
PF_INET = 0x2
|
||||||
|
PF_INET6 = 0xa
|
||||||
|
PF_IPX = 0x4
|
||||||
|
PF_IRDA = 0x17
|
||||||
|
PF_ISDN = 0x22
|
||||||
|
PF_IUCV = 0x20
|
||||||
|
PF_KCM = 0x29
|
||||||
|
PF_KEY = 0xf
|
||||||
|
PF_LLC = 0x1a
|
||||||
|
PF_LOCAL = 0x1
|
||||||
|
PF_MAX = 0x2e
|
||||||
|
PF_MCTP = 0x2d
|
||||||
|
PF_MPLS = 0x1c
|
||||||
|
PF_NETBEUI = 0xd
|
||||||
|
PF_NETLINK = 0x10
|
||||||
|
PF_NETROM = 0x6
|
||||||
|
PF_NFC = 0x27
|
||||||
|
PF_PACKET = 0x11
|
||||||
|
PF_PHONET = 0x23
|
||||||
|
PF_PPPOX = 0x18
|
||||||
|
PF_QIPCRTR = 0x2a
|
||||||
|
PF_R = 0x4
|
||||||
|
PF_RDS = 0x15
|
||||||
|
PF_ROSE = 0xb
|
||||||
|
PF_ROUTE = 0x10
|
||||||
|
PF_RXRPC = 0x21
|
||||||
|
PF_SECURITY = 0xe
|
||||||
|
PF_SMC = 0x2b
|
||||||
|
PF_SNA = 0x16
|
||||||
|
PF_TIPC = 0x1e
|
||||||
|
PF_UNIX = 0x1
|
||||||
|
PF_UNSPEC = 0x0
|
||||||
|
PF_VSOCK = 0x28
|
||||||
|
PF_W = 0x2
|
||||||
|
PF_WANPIPE = 0x19
|
||||||
|
PF_X = 0x1
|
||||||
|
PF_X25 = 0x9
|
||||||
|
PF_XDP = 0x2c
|
||||||
PID_FS_MAGIC = 0x50494446
|
PID_FS_MAGIC = 0x50494446
|
||||||
PIPEFS_MAGIC = 0x50495045
|
PIPEFS_MAGIC = 0x50495045
|
||||||
PPPIOCGNPMODE = 0xc008744c
|
PPPIOCGNPMODE = 0xc008744c
|
||||||
|
|
@ -2758,6 +3047,23 @@ const (
|
||||||
PTRACE_SYSCALL_INFO_NONE = 0x0
|
PTRACE_SYSCALL_INFO_NONE = 0x0
|
||||||
PTRACE_SYSCALL_INFO_SECCOMP = 0x3
|
PTRACE_SYSCALL_INFO_SECCOMP = 0x3
|
||||||
PTRACE_TRACEME = 0x0
|
PTRACE_TRACEME = 0x0
|
||||||
|
PT_AARCH64_MEMTAG_MTE = 0x70000002
|
||||||
|
PT_DYNAMIC = 0x2
|
||||||
|
PT_GNU_EH_FRAME = 0x6474e550
|
||||||
|
PT_GNU_PROPERTY = 0x6474e553
|
||||||
|
PT_GNU_RELRO = 0x6474e552
|
||||||
|
PT_GNU_STACK = 0x6474e551
|
||||||
|
PT_HIOS = 0x6fffffff
|
||||||
|
PT_HIPROC = 0x7fffffff
|
||||||
|
PT_INTERP = 0x3
|
||||||
|
PT_LOAD = 0x1
|
||||||
|
PT_LOOS = 0x60000000
|
||||||
|
PT_LOPROC = 0x70000000
|
||||||
|
PT_NOTE = 0x4
|
||||||
|
PT_NULL = 0x0
|
||||||
|
PT_PHDR = 0x6
|
||||||
|
PT_SHLIB = 0x5
|
||||||
|
PT_TLS = 0x7
|
||||||
P_ALL = 0x0
|
P_ALL = 0x0
|
||||||
P_PGID = 0x2
|
P_PGID = 0x2
|
||||||
P_PID = 0x1
|
P_PID = 0x1
|
||||||
|
|
@ -3091,6 +3397,47 @@ const (
|
||||||
SEEK_MAX = 0x4
|
SEEK_MAX = 0x4
|
||||||
SEEK_SET = 0x0
|
SEEK_SET = 0x0
|
||||||
SELINUX_MAGIC = 0xf97cff8c
|
SELINUX_MAGIC = 0xf97cff8c
|
||||||
|
SHF_ALLOC = 0x2
|
||||||
|
SHF_EXCLUDE = 0x8000000
|
||||||
|
SHF_EXECINSTR = 0x4
|
||||||
|
SHF_GROUP = 0x200
|
||||||
|
SHF_INFO_LINK = 0x40
|
||||||
|
SHF_LINK_ORDER = 0x80
|
||||||
|
SHF_MASKOS = 0xff00000
|
||||||
|
SHF_MASKPROC = 0xf0000000
|
||||||
|
SHF_MERGE = 0x10
|
||||||
|
SHF_ORDERED = 0x4000000
|
||||||
|
SHF_OS_NONCONFORMING = 0x100
|
||||||
|
SHF_RELA_LIVEPATCH = 0x100000
|
||||||
|
SHF_RO_AFTER_INIT = 0x200000
|
||||||
|
SHF_STRINGS = 0x20
|
||||||
|
SHF_TLS = 0x400
|
||||||
|
SHF_WRITE = 0x1
|
||||||
|
SHN_ABS = 0xfff1
|
||||||
|
SHN_COMMON = 0xfff2
|
||||||
|
SHN_HIPROC = 0xff1f
|
||||||
|
SHN_HIRESERVE = 0xffff
|
||||||
|
SHN_LIVEPATCH = 0xff20
|
||||||
|
SHN_LOPROC = 0xff00
|
||||||
|
SHN_LORESERVE = 0xff00
|
||||||
|
SHN_UNDEF = 0x0
|
||||||
|
SHT_DYNAMIC = 0x6
|
||||||
|
SHT_DYNSYM = 0xb
|
||||||
|
SHT_HASH = 0x5
|
||||||
|
SHT_HIPROC = 0x7fffffff
|
||||||
|
SHT_HIUSER = 0xffffffff
|
||||||
|
SHT_LOPROC = 0x70000000
|
||||||
|
SHT_LOUSER = 0x80000000
|
||||||
|
SHT_NOBITS = 0x8
|
||||||
|
SHT_NOTE = 0x7
|
||||||
|
SHT_NULL = 0x0
|
||||||
|
SHT_NUM = 0xc
|
||||||
|
SHT_PROGBITS = 0x1
|
||||||
|
SHT_REL = 0x9
|
||||||
|
SHT_RELA = 0x4
|
||||||
|
SHT_SHLIB = 0xa
|
||||||
|
SHT_STRTAB = 0x3
|
||||||
|
SHT_SYMTAB = 0x2
|
||||||
SHUT_RD = 0x0
|
SHUT_RD = 0x0
|
||||||
SHUT_RDWR = 0x2
|
SHUT_RDWR = 0x2
|
||||||
SHUT_WR = 0x1
|
SHUT_WR = 0x1
|
||||||
|
|
@ -3317,6 +3664,16 @@ const (
|
||||||
STATX_UID = 0x8
|
STATX_UID = 0x8
|
||||||
STATX_WRITE_ATOMIC = 0x10000
|
STATX_WRITE_ATOMIC = 0x10000
|
||||||
STATX__RESERVED = 0x80000000
|
STATX__RESERVED = 0x80000000
|
||||||
|
STB_GLOBAL = 0x1
|
||||||
|
STB_LOCAL = 0x0
|
||||||
|
STB_WEAK = 0x2
|
||||||
|
STT_COMMON = 0x5
|
||||||
|
STT_FILE = 0x4
|
||||||
|
STT_FUNC = 0x2
|
||||||
|
STT_NOTYPE = 0x0
|
||||||
|
STT_OBJECT = 0x1
|
||||||
|
STT_SECTION = 0x3
|
||||||
|
STT_TLS = 0x6
|
||||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||||
SYNC_FILE_RANGE_WRITE = 0x2
|
SYNC_FILE_RANGE_WRITE = 0x2
|
||||||
|
|
@ -3553,6 +3910,8 @@ const (
|
||||||
UTIME_OMIT = 0x3ffffffe
|
UTIME_OMIT = 0x3ffffffe
|
||||||
V9FS_MAGIC = 0x1021997
|
V9FS_MAGIC = 0x1021997
|
||||||
VERASE = 0x2
|
VERASE = 0x2
|
||||||
|
VER_FLG_BASE = 0x1
|
||||||
|
VER_FLG_WEAK = 0x2
|
||||||
VINTR = 0x0
|
VINTR = 0x0
|
||||||
VKILL = 0x3
|
VKILL = 0x3
|
||||||
VLNEXT = 0xf
|
VLNEXT = 0xf
|
||||||
|
|
|
||||||
10
src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go
generated
vendored
10
src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go
generated
vendored
|
|
@ -2238,3 +2238,13 @@ func Mseal(b []byte, flags uint) (err error) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func setMemPolicy(mode int, mask *CPUSet, size int) (err error) {
|
||||||
|
_, _, e1 := Syscall(SYS_SET_MEMPOLICY, uintptr(mode), uintptr(unsafe.Pointer(mask)), uintptr(size))
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
||||||
31
src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go
generated
vendored
31
src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go
generated
vendored
|
|
@ -3590,6 +3590,8 @@ type Nhmsg struct {
|
||||||
Flags uint32
|
Flags uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SizeofNhmsg = 0x8
|
||||||
|
|
||||||
type NexthopGrp struct {
|
type NexthopGrp struct {
|
||||||
Id uint32
|
Id uint32
|
||||||
Weight uint8
|
Weight uint8
|
||||||
|
|
@ -3597,6 +3599,8 @@ type NexthopGrp struct {
|
||||||
Resvd2 uint16
|
Resvd2 uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SizeofNexthopGrp = 0x8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NHA_UNSPEC = 0x0
|
NHA_UNSPEC = 0x0
|
||||||
NHA_ID = 0x1
|
NHA_ID = 0x1
|
||||||
|
|
@ -6332,3 +6336,30 @@ type SockDiagReq struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
const RTM_NEWNVLAN = 0x70
|
const RTM_NEWNVLAN = 0x70
|
||||||
|
|
||||||
|
const (
|
||||||
|
MPOL_BIND = 0x2
|
||||||
|
MPOL_DEFAULT = 0x0
|
||||||
|
MPOL_F_ADDR = 0x2
|
||||||
|
MPOL_F_MEMS_ALLOWED = 0x4
|
||||||
|
MPOL_F_MOF = 0x8
|
||||||
|
MPOL_F_MORON = 0x10
|
||||||
|
MPOL_F_NODE = 0x1
|
||||||
|
MPOL_F_NUMA_BALANCING = 0x2000
|
||||||
|
MPOL_F_RELATIVE_NODES = 0x4000
|
||||||
|
MPOL_F_SHARED = 0x1
|
||||||
|
MPOL_F_STATIC_NODES = 0x8000
|
||||||
|
MPOL_INTERLEAVE = 0x3
|
||||||
|
MPOL_LOCAL = 0x4
|
||||||
|
MPOL_MAX = 0x7
|
||||||
|
MPOL_MF_INTERNAL = 0x10
|
||||||
|
MPOL_MF_LAZY = 0x8
|
||||||
|
MPOL_MF_MOVE_ALL = 0x4
|
||||||
|
MPOL_MF_MOVE = 0x2
|
||||||
|
MPOL_MF_STRICT = 0x1
|
||||||
|
MPOL_MF_VALID = 0x7
|
||||||
|
MPOL_MODE_FLAGS = 0xe000
|
||||||
|
MPOL_PREFERRED = 0x1
|
||||||
|
MPOL_PREFERRED_MANY = 0x5
|
||||||
|
MPOL_WEIGHTED_INTERLEAVE = 0x6
|
||||||
|
)
|
||||||
|
|
|
||||||
15
src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
15
src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
|
|
@ -892,8 +892,12 @@ const socket_error = uintptr(^uint32(0))
|
||||||
//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
|
//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
|
||||||
//sys getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx
|
//sys getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx
|
||||||
//sys GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex
|
//sys GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex
|
||||||
|
//sys GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) = iphlpapi.GetIpForwardEntry2
|
||||||
|
//sys GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) = iphlpapi.GetIpForwardTable2
|
||||||
//sys GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry
|
//sys GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry
|
||||||
|
//sys FreeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable
|
||||||
//sys NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange
|
//sys NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange
|
||||||
|
//sys NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyRouteChange2
|
||||||
//sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange
|
//sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange
|
||||||
//sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2
|
//sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2
|
||||||
|
|
||||||
|
|
@ -916,6 +920,17 @@ type RawSockaddrInet6 struct {
|
||||||
Scope_id uint32
|
Scope_id uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RawSockaddrInet is a union that contains an IPv4, an IPv6 address, or an address family. See
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-sockaddr_inet.
|
||||||
|
//
|
||||||
|
// A [*RawSockaddrInet] may be converted to a [*RawSockaddrInet4] or [*RawSockaddrInet6] using
|
||||||
|
// unsafe, depending on the address family.
|
||||||
|
type RawSockaddrInet struct {
|
||||||
|
Family uint16
|
||||||
|
Port uint16
|
||||||
|
Data [6]uint32
|
||||||
|
}
|
||||||
|
|
||||||
type RawSockaddr struct {
|
type RawSockaddr struct {
|
||||||
Family uint16
|
Family uint16
|
||||||
Data [14]int8
|
Data [14]int8
|
||||||
|
|
|
||||||
76
src/cmd/vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
76
src/cmd/vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
|
|
@ -2320,6 +2320,82 @@ type MibIfRow2 struct {
|
||||||
OutQLen uint64
|
OutQLen uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IP_ADDRESS_PREFIX stores an IP address prefix. See
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-ip_address_prefix.
|
||||||
|
type IpAddressPrefix struct {
|
||||||
|
Prefix RawSockaddrInet
|
||||||
|
PrefixLength uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// NL_ROUTE_ORIGIN enumeration from nldef.h or
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_route_origin.
|
||||||
|
const (
|
||||||
|
NlroManual = 0
|
||||||
|
NlroWellKnown = 1
|
||||||
|
NlroDHCP = 2
|
||||||
|
NlroRouterAdvertisement = 3
|
||||||
|
Nlro6to4 = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
// NL_ROUTE_ORIGIN enumeration from nldef.h or
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_route_protocol.
|
||||||
|
const (
|
||||||
|
MIB_IPPROTO_OTHER = 1
|
||||||
|
MIB_IPPROTO_LOCAL = 2
|
||||||
|
MIB_IPPROTO_NETMGMT = 3
|
||||||
|
MIB_IPPROTO_ICMP = 4
|
||||||
|
MIB_IPPROTO_EGP = 5
|
||||||
|
MIB_IPPROTO_GGP = 6
|
||||||
|
MIB_IPPROTO_HELLO = 7
|
||||||
|
MIB_IPPROTO_RIP = 8
|
||||||
|
MIB_IPPROTO_IS_IS = 9
|
||||||
|
MIB_IPPROTO_ES_IS = 10
|
||||||
|
MIB_IPPROTO_CISCO = 11
|
||||||
|
MIB_IPPROTO_BBN = 12
|
||||||
|
MIB_IPPROTO_OSPF = 13
|
||||||
|
MIB_IPPROTO_BGP = 14
|
||||||
|
MIB_IPPROTO_IDPR = 15
|
||||||
|
MIB_IPPROTO_EIGRP = 16
|
||||||
|
MIB_IPPROTO_DVMRP = 17
|
||||||
|
MIB_IPPROTO_RPL = 18
|
||||||
|
MIB_IPPROTO_DHCP = 19
|
||||||
|
MIB_IPPROTO_NT_AUTOSTATIC = 10002
|
||||||
|
MIB_IPPROTO_NT_STATIC = 10006
|
||||||
|
MIB_IPPROTO_NT_STATIC_NON_DOD = 10007
|
||||||
|
)
|
||||||
|
|
||||||
|
// MIB_IPFORWARD_ROW2 stores information about an IP route entry. See
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_row2.
|
||||||
|
type MibIpForwardRow2 struct {
|
||||||
|
InterfaceLuid uint64
|
||||||
|
InterfaceIndex uint32
|
||||||
|
DestinationPrefix IpAddressPrefix
|
||||||
|
NextHop RawSockaddrInet
|
||||||
|
SitePrefixLength uint8
|
||||||
|
ValidLifetime uint32
|
||||||
|
PreferredLifetime uint32
|
||||||
|
Metric uint32
|
||||||
|
Protocol uint32
|
||||||
|
Loopback uint8
|
||||||
|
AutoconfigureAddress uint8
|
||||||
|
Publish uint8
|
||||||
|
Immortal uint8
|
||||||
|
Age uint32
|
||||||
|
Origin uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// MIB_IPFORWARD_TABLE2 contains a table of IP route entries. See
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_table2.
|
||||||
|
type MibIpForwardTable2 struct {
|
||||||
|
NumEntries uint32
|
||||||
|
Table [1]MibIpForwardRow2
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rows returns the IP route entries in the table.
|
||||||
|
func (t *MibIpForwardTable2) Rows() []MibIpForwardRow2 {
|
||||||
|
return unsafe.Slice(&t.Table[0], t.NumEntries)
|
||||||
|
}
|
||||||
|
|
||||||
// MIB_UNICASTIPADDRESS_ROW stores information about a unicast IP address. See
|
// MIB_UNICASTIPADDRESS_ROW stores information about a unicast IP address. See
|
||||||
// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_row.
|
// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_row.
|
||||||
type MibUnicastIpAddressRow struct {
|
type MibUnicastIpAddressRow struct {
|
||||||
|
|
|
||||||
37
src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
generated
vendored
37
src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
generated
vendored
|
|
@ -182,13 +182,17 @@ var (
|
||||||
procDwmGetWindowAttribute = moddwmapi.NewProc("DwmGetWindowAttribute")
|
procDwmGetWindowAttribute = moddwmapi.NewProc("DwmGetWindowAttribute")
|
||||||
procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute")
|
procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute")
|
||||||
procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2")
|
procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2")
|
||||||
|
procFreeMibTable = modiphlpapi.NewProc("FreeMibTable")
|
||||||
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
|
procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
|
||||||
procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo")
|
procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo")
|
||||||
procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx")
|
procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx")
|
||||||
procGetIfEntry = modiphlpapi.NewProc("GetIfEntry")
|
procGetIfEntry = modiphlpapi.NewProc("GetIfEntry")
|
||||||
procGetIfEntry2Ex = modiphlpapi.NewProc("GetIfEntry2Ex")
|
procGetIfEntry2Ex = modiphlpapi.NewProc("GetIfEntry2Ex")
|
||||||
|
procGetIpForwardEntry2 = modiphlpapi.NewProc("GetIpForwardEntry2")
|
||||||
|
procGetIpForwardTable2 = modiphlpapi.NewProc("GetIpForwardTable2")
|
||||||
procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry")
|
procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry")
|
||||||
procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange")
|
procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange")
|
||||||
|
procNotifyRouteChange2 = modiphlpapi.NewProc("NotifyRouteChange2")
|
||||||
procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange")
|
procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange")
|
||||||
procAddDllDirectory = modkernel32.NewProc("AddDllDirectory")
|
procAddDllDirectory = modkernel32.NewProc("AddDllDirectory")
|
||||||
procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject")
|
procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject")
|
||||||
|
|
@ -1624,6 +1628,11 @@ func CancelMibChangeNotify2(notificationHandle Handle) (errcode error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FreeMibTable(memory unsafe.Pointer) {
|
||||||
|
syscall.SyscallN(procFreeMibTable.Addr(), uintptr(memory))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
|
func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
|
||||||
r0, _, _ := syscall.SyscallN(procGetAdaptersAddresses.Addr(), uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)))
|
r0, _, _ := syscall.SyscallN(procGetAdaptersAddresses.Addr(), uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)))
|
||||||
if r0 != 0 {
|
if r0 != 0 {
|
||||||
|
|
@ -1664,6 +1673,22 @@ func GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) {
|
||||||
|
r0, _, _ := syscall.SyscallN(procGetIpForwardEntry2.Addr(), uintptr(unsafe.Pointer(row)))
|
||||||
|
if r0 != 0 {
|
||||||
|
errcode = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) {
|
||||||
|
r0, _, _ := syscall.SyscallN(procGetIpForwardTable2.Addr(), uintptr(family), uintptr(unsafe.Pointer(table)))
|
||||||
|
if r0 != 0 {
|
||||||
|
errcode = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) {
|
func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) {
|
||||||
r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressEntry.Addr(), uintptr(unsafe.Pointer(row)))
|
r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressEntry.Addr(), uintptr(unsafe.Pointer(row)))
|
||||||
if r0 != 0 {
|
if r0 != 0 {
|
||||||
|
|
@ -1684,6 +1709,18 @@ func NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsa
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
|
||||||
|
var _p0 uint32
|
||||||
|
if initialNotification {
|
||||||
|
_p0 = 1
|
||||||
|
}
|
||||||
|
r0, _, _ := syscall.SyscallN(procNotifyRouteChange2.Addr(), uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)))
|
||||||
|
if r0 != 0 {
|
||||||
|
errcode = syscall.Errno(r0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
|
func NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) {
|
||||||
var _p0 uint32
|
var _p0 uint32
|
||||||
if initialNotification {
|
if initialNotification {
|
||||||
|
|
|
||||||
1
src/cmd/vendor/golang.org/x/telemetry/codereview.cfg
generated
vendored
Normal file
1
src/cmd/vendor/golang.org/x/telemetry/codereview.cfg
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
issuerepo: golang/go
|
||||||
5
src/cmd/vendor/golang.org/x/tools/go/analysis/diagnostic.go
generated
vendored
5
src/cmd/vendor/golang.org/x/tools/go/analysis/diagnostic.go
generated
vendored
|
|
@ -33,8 +33,9 @@ type Diagnostic struct {
|
||||||
URL string
|
URL string
|
||||||
|
|
||||||
// SuggestedFixes is an optional list of fixes to address the
|
// SuggestedFixes is an optional list of fixes to address the
|
||||||
// problem described by the diagnostic. Each one represents
|
// problem described by the diagnostic. Each one represents an
|
||||||
// an alternative strategy; at most one may be applied.
|
// alternative strategy, and should have a distinct and
|
||||||
|
// descriptive message; at most one may be applied.
|
||||||
//
|
//
|
||||||
// Fixes for different diagnostics should be treated as
|
// Fixes for different diagnostics should be treated as
|
||||||
// independent changes to the same baseline file state,
|
// independent changes to the same baseline file state,
|
||||||
|
|
|
||||||
159
src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
generated
vendored
159
src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
generated
vendored
|
|
@ -13,22 +13,20 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
)
|
)
|
||||||
|
|
||||||
// flags common to all {single,multi,unit}checkers.
|
// flags common to all {single,multi,unit}checkers.
|
||||||
var (
|
var (
|
||||||
JSON = false // -json
|
JSON = false // -json
|
||||||
Context = -1 // -c=N: if N>0, display offending line plus N lines of context
|
Context = -1 // -c=N: if N>0, display offending line plus N lines of context
|
||||||
Fix bool // -fix
|
Fix bool // -fix
|
||||||
diffFlag bool // -diff (changes [ApplyFixes] behavior)
|
Diff bool // -diff
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parse creates a flag for each of the analyzer's flags,
|
// Parse creates a flag for each of the analyzer's flags,
|
||||||
|
|
@ -78,7 +76,7 @@ func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
|
||||||
flag.BoolVar(&JSON, "json", JSON, "emit JSON output")
|
flag.BoolVar(&JSON, "json", JSON, "emit JSON output")
|
||||||
flag.IntVar(&Context, "c", Context, `display offending line with this many lines of context`)
|
flag.IntVar(&Context, "c", Context, `display offending line with this many lines of context`)
|
||||||
flag.BoolVar(&Fix, "fix", false, "apply all suggested fixes")
|
flag.BoolVar(&Fix, "fix", false, "apply all suggested fixes")
|
||||||
flag.BoolVar(&diffFlag, "diff", false, "with -fix, don't update the files, but print a unified diff")
|
flag.BoolVar(&Diff, "diff", false, "with -fix, don't update the files, but print a unified diff")
|
||||||
|
|
||||||
// Add shims for legacy vet flags to enable existing
|
// Add shims for legacy vet flags to enable existing
|
||||||
// scripts that run vet to continue to work.
|
// scripts that run vet to continue to work.
|
||||||
|
|
@ -310,150 +308,3 @@ var vetLegacyFlags = map[string]string{
|
||||||
"unusedfuncs": "unusedresult.funcs",
|
"unusedfuncs": "unusedresult.funcs",
|
||||||
"unusedstringmethods": "unusedresult.stringmethods",
|
"unusedstringmethods": "unusedresult.stringmethods",
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- output helpers common to all drivers ----
|
|
||||||
//
|
|
||||||
// These functions should not depend on global state (flags)!
|
|
||||||
// Really they belong in a different package.
|
|
||||||
|
|
||||||
// TODO(adonovan): don't accept an io.Writer if we don't report errors.
|
|
||||||
// Either accept a bytes.Buffer (infallible), or return a []byte.
|
|
||||||
|
|
||||||
// PrintPlain prints a diagnostic in plain text form.
|
|
||||||
// If contextLines is nonnegative, it also prints the
|
|
||||||
// offending line plus this many lines of context.
|
|
||||||
func PrintPlain(out io.Writer, fset *token.FileSet, contextLines int, diag analysis.Diagnostic) {
|
|
||||||
print := func(pos, end token.Pos, message string) {
|
|
||||||
posn := fset.Position(pos)
|
|
||||||
fmt.Fprintf(out, "%s: %s\n", posn, message)
|
|
||||||
|
|
||||||
// show offending line plus N lines of context.
|
|
||||||
if contextLines >= 0 {
|
|
||||||
end := fset.Position(end)
|
|
||||||
if !end.IsValid() {
|
|
||||||
end = posn
|
|
||||||
}
|
|
||||||
// TODO(adonovan): highlight the portion of the line indicated
|
|
||||||
// by pos...end using ASCII art, terminal colors, etc?
|
|
||||||
data, _ := os.ReadFile(posn.Filename)
|
|
||||||
lines := strings.Split(string(data), "\n")
|
|
||||||
for i := posn.Line - contextLines; i <= end.Line+contextLines; i++ {
|
|
||||||
if 1 <= i && i <= len(lines) {
|
|
||||||
fmt.Fprintf(out, "%d\t%s\n", i, lines[i-1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print(diag.Pos, diag.End, diag.Message)
|
|
||||||
for _, rel := range diag.Related {
|
|
||||||
print(rel.Pos, rel.End, "\t"+rel.Message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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]any
|
|
||||||
|
|
||||||
// A TextEdit describes the replacement of a portion of a file.
|
|
||||||
// Start and End are zero-based half-open indices into the original byte
|
|
||||||
// sequence of the file, and New is the new text.
|
|
||||||
type JSONTextEdit struct {
|
|
||||||
Filename string `json:"filename"`
|
|
||||||
Start int `json:"start"`
|
|
||||||
End int `json:"end"`
|
|
||||||
New string `json:"new"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// A JSONSuggestedFix describes an edit that should be applied as a whole or not
|
|
||||||
// at all. It might contain multiple TextEdits/text_edits if the SuggestedFix
|
|
||||||
// consists of multiple non-contiguous edits.
|
|
||||||
type JSONSuggestedFix struct {
|
|
||||||
Message string `json:"message"`
|
|
||||||
Edits []JSONTextEdit `json:"edits"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// A JSONDiagnostic describes the JSON schema of an analysis.Diagnostic.
|
|
||||||
//
|
|
||||||
// TODO(matloob): include End position if present.
|
|
||||||
type JSONDiagnostic struct {
|
|
||||||
Category string `json:"category,omitempty"`
|
|
||||||
Posn string `json:"posn"` // e.g. "file.go:line:column"
|
|
||||||
Message string `json:"message"`
|
|
||||||
SuggestedFixes []JSONSuggestedFix `json:"suggested_fixes,omitempty"`
|
|
||||||
Related []JSONRelatedInformation `json:"related,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// A JSONRelated describes a secondary position and message related to
|
|
||||||
// a primary diagnostic.
|
|
||||||
//
|
|
||||||
// TODO(adonovan): include End position if present.
|
|
||||||
type JSONRelatedInformation struct {
|
|
||||||
Posn string `json:"posn"` // e.g. "file.go:line:column"
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 any
|
|
||||||
if err != nil {
|
|
||||||
type jsonError struct {
|
|
||||||
Err string `json:"error"`
|
|
||||||
}
|
|
||||||
v = jsonError{err.Error()}
|
|
||||||
} else if len(diags) > 0 {
|
|
||||||
diagnostics := make([]JSONDiagnostic, 0, len(diags))
|
|
||||||
for _, f := range diags {
|
|
||||||
var fixes []JSONSuggestedFix
|
|
||||||
for _, fix := range f.SuggestedFixes {
|
|
||||||
var edits []JSONTextEdit
|
|
||||||
for _, edit := range fix.TextEdits {
|
|
||||||
edits = append(edits, JSONTextEdit{
|
|
||||||
Filename: fset.Position(edit.Pos).Filename,
|
|
||||||
Start: fset.Position(edit.Pos).Offset,
|
|
||||||
End: fset.Position(edit.End).Offset,
|
|
||||||
New: string(edit.NewText),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
fixes = append(fixes, JSONSuggestedFix{
|
|
||||||
Message: fix.Message,
|
|
||||||
Edits: edits,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
var related []JSONRelatedInformation
|
|
||||||
for _, r := range f.Related {
|
|
||||||
related = append(related, JSONRelatedInformation{
|
|
||||||
Posn: fset.Position(r.Pos).String(),
|
|
||||||
Message: r.Message,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
jdiag := JSONDiagnostic{
|
|
||||||
Category: f.Category,
|
|
||||||
Posn: fset.Position(f.Pos).String(),
|
|
||||||
Message: f.Message,
|
|
||||||
SuggestedFixes: fixes,
|
|
||||||
Related: related,
|
|
||||||
}
|
|
||||||
diagnostics = append(diagnostics, jdiag)
|
|
||||||
}
|
|
||||||
v = diagnostics
|
|
||||||
}
|
|
||||||
if v != nil {
|
|
||||||
m, ok := tree[id]
|
|
||||||
if !ok {
|
|
||||||
m = make(map[string]any)
|
|
||||||
tree[id] = m
|
|
||||||
}
|
|
||||||
m[name] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tree JSONTree) Print(out io.Writer) error {
|
|
||||||
data, err := json.MarshalIndent(tree, "", "\t")
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("internal error: JSON marshaling failed: %v", err)
|
|
||||||
}
|
|
||||||
_, err = fmt.Fprintf(out, "%s\n", data)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/appends/appends.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/appends/appends.go
generated
vendored
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -23,7 +23,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "appends",
|
Name: "appends",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "appends"),
|
Doc: analyzerutil.MustExtractDoc(doc, "appends"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/appends",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/appends",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
generated
vendored
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const Doc = "report mismatches between assembly files and Go declarations"
|
const Doc = "report mismatches between assembly files and Go declarations"
|
||||||
|
|
@ -175,7 +175,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
|
|
||||||
Files:
|
Files:
|
||||||
for _, fname := range sfiles {
|
for _, fname := range sfiles {
|
||||||
content, tf, err := analysisinternal.ReadFile(pass, fname)
|
content, tf, err := analyzerutil.ReadFile(pass, fname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go
generated
vendored
|
|
@ -18,7 +18,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
|
|
@ -29,7 +29,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "assign",
|
Name: "assign",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "assign"),
|
Doc: analyzerutil.MustExtractDoc(doc, "assign"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/assign",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/assign",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/atomic/atomic.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/atomic/atomic.go
generated
vendored
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
@ -23,7 +23,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "atomic",
|
Name: "atomic",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "atomic"),
|
Doc: analyzerutil.MustExtractDoc(doc, "atomic"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/atomic",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/atomic",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
RunDespiteErrors: true,
|
RunDespiteErrors: true,
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go
generated
vendored
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const Doc = "check //go:build and // +build directives"
|
const Doc = "check //go:build and // +build directives"
|
||||||
|
|
@ -86,7 +86,7 @@ func checkOtherFile(pass *analysis.Pass, filename string) error {
|
||||||
|
|
||||||
// We cannot use the Go parser, since this may not be a Go source file.
|
// We cannot use the Go parser, since this may not be a Go source file.
|
||||||
// Read the raw bytes instead.
|
// Read the raw bytes instead.
|
||||||
content, tf, err := analysisinternal.ReadFile(pass, filename)
|
content, tf, err := analyzerutil.ReadFile(pass, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go
generated
vendored
|
|
@ -350,8 +350,8 @@ func typeOKForCgoCall(t types.Type, m map[types.Type]bool) bool {
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
return typeOKForCgoCall(t.Elem(), m)
|
return typeOKForCgoCall(t.Elem(), m)
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
for i := 0; i < t.NumFields(); i++ {
|
for field := range t.Fields() {
|
||||||
if !typeOKForCgoCall(t.Field(i).Type(), m) {
|
if !typeOKForCgoCall(field.Type(), m) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go
generated
vendored
|
|
@ -328,8 +328,8 @@ func lockPath(tpkg *types.Package, typ types.Type, seen map[types.Type]bool) typ
|
||||||
|
|
||||||
ttyp, ok := typ.Underlying().(*types.Tuple)
|
ttyp, ok := typ.Underlying().(*types.Tuple)
|
||||||
if ok {
|
if ok {
|
||||||
for i := 0; i < ttyp.Len(); i++ {
|
for v := range ttyp.Variables() {
|
||||||
subpath := lockPath(tpkg, ttyp.At(i).Type(), seen)
|
subpath := lockPath(tpkg, v.Type(), seen)
|
||||||
if subpath != nil {
|
if subpath != nil {
|
||||||
return append(subpath, typ.String())
|
return append(subpath, typ.String())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
90
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ctrlflow/ctrlflow.go
generated
vendored
90
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ctrlflow/ctrlflow.go
generated
vendored
|
|
@ -16,9 +16,12 @@ import (
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
|
"golang.org/x/tools/go/analysis/passes/internal/ctrlflowinternal"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/cfg"
|
"golang.org/x/tools/go/cfg"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
|
"golang.org/x/tools/internal/cfginternal"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
|
|
@ -26,7 +29,7 @@ var Analyzer = &analysis.Analyzer{
|
||||||
Doc: "build a control-flow graph",
|
Doc: "build a control-flow graph",
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/ctrlflow",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/ctrlflow",
|
||||||
Run: run,
|
Run: run,
|
||||||
ResultType: reflect.TypeOf(new(CFGs)),
|
ResultType: reflect.TypeFor[*CFGs](),
|
||||||
FactTypes: []analysis.Fact{new(noReturn)},
|
FactTypes: []analysis.Fact{new(noReturn)},
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
}
|
}
|
||||||
|
|
@ -44,7 +47,20 @@ type CFGs struct {
|
||||||
defs map[*ast.Ident]types.Object // from Pass.TypesInfo.Defs
|
defs map[*ast.Ident]types.Object // from Pass.TypesInfo.Defs
|
||||||
funcDecls map[*types.Func]*declInfo
|
funcDecls map[*types.Func]*declInfo
|
||||||
funcLits map[*ast.FuncLit]*litInfo
|
funcLits map[*ast.FuncLit]*litInfo
|
||||||
pass *analysis.Pass // transient; nil after construction
|
noReturn map[*types.Func]bool // functions lacking a reachable return statement
|
||||||
|
pass *analysis.Pass // transient; nil after construction
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(adonovan): add (*CFGs).NoReturn to public API.
|
||||||
|
func (c *CFGs) isNoReturn(fn *types.Func) bool {
|
||||||
|
return c.noReturn[fn]
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Expose the hidden method to callers in x/tools.
|
||||||
|
ctrlflowinternal.NoReturn = func(c any, fn *types.Func) bool {
|
||||||
|
return c.(*CFGs).isNoReturn(fn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CFGs has two maps: funcDecls for named functions and funcLits for
|
// CFGs has two maps: funcDecls for named functions and funcLits for
|
||||||
|
|
@ -54,15 +70,14 @@ type CFGs struct {
|
||||||
// *types.Func but not the other way.
|
// *types.Func but not the other way.
|
||||||
|
|
||||||
type declInfo struct {
|
type declInfo struct {
|
||||||
decl *ast.FuncDecl
|
decl *ast.FuncDecl
|
||||||
cfg *cfg.CFG // iff decl.Body != nil
|
cfg *cfg.CFG // iff decl.Body != nil
|
||||||
started bool // to break cycles
|
started bool // to break cycles
|
||||||
noReturn bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type litInfo struct {
|
type litInfo struct {
|
||||||
cfg *cfg.CFG
|
cfg *cfg.CFG
|
||||||
noReturn bool
|
noReturn bool // (currently unused)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FuncDecl returns the control-flow graph for a named function.
|
// FuncDecl returns the control-flow graph for a named function.
|
||||||
|
|
@ -118,6 +133,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
defs: pass.TypesInfo.Defs,
|
defs: pass.TypesInfo.Defs,
|
||||||
funcDecls: funcDecls,
|
funcDecls: funcDecls,
|
||||||
funcLits: funcLits,
|
funcLits: funcLits,
|
||||||
|
noReturn: make(map[*types.Func]bool),
|
||||||
pass: pass,
|
pass: pass,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,7 +154,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
li := funcLits[lit]
|
li := funcLits[lit]
|
||||||
if li.cfg == nil {
|
if li.cfg == nil {
|
||||||
li.cfg = cfg.New(lit.Body, c.callMayReturn)
|
li.cfg = cfg.New(lit.Body, c.callMayReturn)
|
||||||
if !hasReachableReturn(li.cfg) {
|
if cfginternal.IsNoReturn(li.cfg) {
|
||||||
li.noReturn = true
|
li.noReturn = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -158,27 +174,28 @@ func (c *CFGs) buildDecl(fn *types.Func, di *declInfo) {
|
||||||
// The buildDecl call tree thus resembles the static call graph.
|
// The buildDecl call tree thus resembles the static call graph.
|
||||||
// We mark each node when we start working on it to break cycles.
|
// We mark each node when we start working on it to break cycles.
|
||||||
|
|
||||||
if !di.started { // break cycle
|
if di.started {
|
||||||
di.started = true
|
return // break cycle
|
||||||
|
}
|
||||||
|
di.started = true
|
||||||
|
|
||||||
if isIntrinsicNoReturn(fn) {
|
noreturn := isIntrinsicNoReturn(fn)
|
||||||
di.noReturn = true
|
|
||||||
}
|
|
||||||
if di.decl.Body != nil {
|
|
||||||
di.cfg = cfg.New(di.decl.Body, c.callMayReturn)
|
|
||||||
if !hasReachableReturn(di.cfg) {
|
|
||||||
di.noReturn = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if di.noReturn {
|
|
||||||
c.pass.ExportObjectFact(fn, new(noReturn))
|
|
||||||
}
|
|
||||||
|
|
||||||
// debugging
|
if di.decl.Body != nil {
|
||||||
if false {
|
di.cfg = cfg.New(di.decl.Body, c.callMayReturn)
|
||||||
log.Printf("CFG for %s:\n%s (noreturn=%t)\n", fn, di.cfg.Format(c.pass.Fset), di.noReturn)
|
if cfginternal.IsNoReturn(di.cfg) {
|
||||||
|
noreturn = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if noreturn {
|
||||||
|
c.pass.ExportObjectFact(fn, new(noReturn))
|
||||||
|
c.noReturn[fn] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// debugging
|
||||||
|
if false {
|
||||||
|
log.Printf("CFG for %s:\n%s (noreturn=%t)\n", fn, di.cfg.Format(c.pass.Fset), noreturn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// callMayReturn reports whether the called function may return.
|
// callMayReturn reports whether the called function may return.
|
||||||
|
|
@ -201,31 +218,26 @@ func (c *CFGs) callMayReturn(call *ast.CallExpr) (r bool) {
|
||||||
// Function or method declared in this package?
|
// Function or method declared in this package?
|
||||||
if di, ok := c.funcDecls[fn]; ok {
|
if di, ok := c.funcDecls[fn]; ok {
|
||||||
c.buildDecl(fn, di)
|
c.buildDecl(fn, di)
|
||||||
return !di.noReturn
|
return !c.noReturn[fn]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not declared in this package.
|
// Not declared in this package.
|
||||||
// Is there a fact from another package?
|
// Is there a fact from another package?
|
||||||
return !c.pass.ImportObjectFact(fn, new(noReturn))
|
if c.pass.ImportObjectFact(fn, new(noReturn)) {
|
||||||
|
c.noReturn[fn] = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
var panicBuiltin = types.Universe.Lookup("panic").(*types.Builtin)
|
var panicBuiltin = types.Universe.Lookup("panic").(*types.Builtin)
|
||||||
|
|
||||||
func hasReachableReturn(g *cfg.CFG) bool {
|
|
||||||
for _, b := range g.Blocks {
|
|
||||||
if b.Live && b.Return() != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// isIntrinsicNoReturn reports whether a function intrinsically never
|
// isIntrinsicNoReturn reports whether a function intrinsically never
|
||||||
// returns because it stops execution of the calling thread.
|
// returns because it stops execution of the calling thread.
|
||||||
// It is the base case in the recursion.
|
// It is the base case in the recursion.
|
||||||
func isIntrinsicNoReturn(fn *types.Func) bool {
|
func isIntrinsicNoReturn(fn *types.Func) bool {
|
||||||
// Add functions here as the need arises, but don't allocate memory.
|
// Add functions here as the need arises, but don't allocate memory.
|
||||||
path, name := fn.Pkg().Path(), fn.Name()
|
return typesinternal.IsFunctionNamed(fn, "syscall", "Exit", "ExitProcess", "ExitThread") ||
|
||||||
return path == "syscall" && (name == "Exit" || name == "ExitProcess" || name == "ExitThread") ||
|
typesinternal.IsFunctionNamed(fn, "runtime", "Goexit")
|
||||||
path == "runtime" && name == "Goexit"
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/defers/defers.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/defers/defers.go
generated
vendored
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -23,7 +23,7 @@ var doc string
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "defers",
|
Name: "defers",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "defers"),
|
Doc: analyzerutil.MustExtractDoc(doc, "defers"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/defers",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/defers",
|
||||||
Run: run,
|
Run: run,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/directive/directive.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/directive/directive.go
generated
vendored
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const Doc = `check Go toolchain directives such as //go:debug
|
const Doc = `check Go toolchain directives such as //go:debug
|
||||||
|
|
@ -86,7 +86,7 @@ func checkGoFile(pass *analysis.Pass, f *ast.File) {
|
||||||
func checkOtherFile(pass *analysis.Pass, filename string) error {
|
func checkOtherFile(pass *analysis.Pass, filename string) error {
|
||||||
// We cannot use the Go parser, since is not a Go source file.
|
// We cannot use the Go parser, since is not a Go source file.
|
||||||
// Read the raw bytes instead.
|
// Read the raw bytes instead.
|
||||||
content, tf, err := analysisinternal.ReadFile(pass, filename)
|
content, tf, err := analyzerutil.ReadFile(pass, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go
generated
vendored
2
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go
generated
vendored
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"go/types"
|
"go/types"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go
generated
vendored
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const Doc = "report assembly that clobbers the frame pointer before saving it"
|
const Doc = "report assembly that clobbers the frame pointer before saving it"
|
||||||
|
|
@ -98,7 +98,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, fname := range sfiles {
|
for _, fname := range sfiles {
|
||||||
content, tf, err := analysisinternal.ReadFile(pass, fname)
|
content, tf, err := analyzerutil.ReadFile(pass, fname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/hostport/hostport.go
generated
vendored
2
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/hostport/hostport.go
generated
vendored
|
|
@ -17,7 +17,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go
generated
vendored
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/typeparams"
|
"golang.org/x/tools/internal/typeparams"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "ifaceassert",
|
Name: "ifaceassert",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "ifaceassert"),
|
Doc: analyzerutil.MustExtractDoc(doc, "ifaceassert"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/ifaceassert",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/ifaceassert",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,10 @@ import (
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/diff"
|
"golang.org/x/tools/internal/diff"
|
||||||
|
"golang.org/x/tools/internal/moreiters"
|
||||||
"golang.org/x/tools/internal/packagepath"
|
"golang.org/x/tools/internal/packagepath"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/refactor/inline"
|
"golang.org/x/tools/internal/refactor/inline"
|
||||||
|
|
@ -34,7 +35,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "inline",
|
Name: "inline",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "inline"),
|
Doc: analyzerutil.MustExtractDoc(doc, "inline"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/inline",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/inline",
|
||||||
Run: run,
|
Run: run,
|
||||||
FactTypes: []analysis.Fact{
|
FactTypes: []analysis.Fact{
|
||||||
|
|
@ -132,8 +133,6 @@ func (a *analyzer) HandleConst(nameIdent, rhsIdent *ast.Ident) {
|
||||||
|
|
||||||
// inline inlines each static call to an inlinable function
|
// inline inlines each static call to an inlinable function
|
||||||
// and each reference to an inlinable constant or type alias.
|
// and each reference to an inlinable constant or type alias.
|
||||||
//
|
|
||||||
// TODO(adonovan): handle multiple diffs that each add the same import.
|
|
||||||
func (a *analyzer) inline() {
|
func (a *analyzer) inline() {
|
||||||
for cur := range a.root.Preorder((*ast.CallExpr)(nil), (*ast.Ident)(nil)) {
|
for cur := range a.root.Preorder((*ast.CallExpr)(nil), (*ast.Ident)(nil)) {
|
||||||
switch n := cur.Node().(type) {
|
switch n := cur.Node().(type) {
|
||||||
|
|
@ -167,6 +166,10 @@ func (a *analyzer) inlineCall(call *ast.CallExpr, cur inspector.Cursor) {
|
||||||
return // nope
|
return // nope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if a.withinTestOf(cur, fn) {
|
||||||
|
return // don't inline a function from within its own test
|
||||||
|
}
|
||||||
|
|
||||||
// Inline the call.
|
// Inline the call.
|
||||||
content, err := a.readFile(call)
|
content, err := a.readFile(call)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -229,6 +232,44 @@ func (a *analyzer) inlineCall(call *ast.CallExpr, cur inspector.Cursor) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// withinTestOf reports whether cur is within a dedicated test
|
||||||
|
// function for the inlinable target function.
|
||||||
|
// A call within its dedicated test should not be inlined.
|
||||||
|
func (a *analyzer) withinTestOf(cur inspector.Cursor, target *types.Func) bool {
|
||||||
|
curFuncDecl, ok := moreiters.First(cur.Enclosing((*ast.FuncDecl)(nil)))
|
||||||
|
if !ok {
|
||||||
|
return false // not in a function
|
||||||
|
}
|
||||||
|
funcDecl := curFuncDecl.Node().(*ast.FuncDecl)
|
||||||
|
if funcDecl.Recv != nil {
|
||||||
|
return false // not a test func
|
||||||
|
}
|
||||||
|
if strings.TrimSuffix(a.pass.Pkg.Path(), "_test") != target.Pkg().Path() {
|
||||||
|
return false // different package
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(a.pass.Fset.File(funcDecl.Pos()).Name(), "_test.go") {
|
||||||
|
return false // not a test file
|
||||||
|
}
|
||||||
|
|
||||||
|
// Computed expected SYMBOL portion of "TestSYMBOL_comment"
|
||||||
|
// for the target symbol.
|
||||||
|
symbol := target.Name()
|
||||||
|
if recv := target.Signature().Recv(); recv != nil {
|
||||||
|
_, named := typesinternal.ReceiverNamed(recv)
|
||||||
|
symbol = named.Obj().Name() + "_" + symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(adonovan): use a proper Test function parser.
|
||||||
|
fname := funcDecl.Name.Name
|
||||||
|
for _, pre := range []string{"Test", "Example", "Bench"} {
|
||||||
|
if fname == pre+symbol || strings.HasPrefix(fname, pre+symbol+"_") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// If tn is the TypeName of an inlinable alias, suggest inlining its use at cur.
|
// If tn is the TypeName of an inlinable alias, suggest inlining its use at cur.
|
||||||
func (a *analyzer) inlineAlias(tn *types.TypeName, curId inspector.Cursor) {
|
func (a *analyzer) inlineAlias(tn *types.TypeName, curId inspector.Cursor) {
|
||||||
inalias, ok := a.inlinableAliases[tn]
|
inalias, ok := a.inlinableAliases[tn]
|
||||||
|
|
@ -375,8 +416,8 @@ func typenames(t types.Type) []*types.TypeName {
|
||||||
visit(t.Key())
|
visit(t.Key())
|
||||||
visit(t.Elem())
|
visit(t.Elem())
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
for i := range t.NumFields() {
|
for field := range t.Fields() {
|
||||||
visit(t.Field(i).Type())
|
visit(field.Type())
|
||||||
}
|
}
|
||||||
case *types.Signature:
|
case *types.Signature:
|
||||||
// Ignore the receiver: although it may be present, it has no meaning
|
// Ignore the receiver: although it may be present, it has no meaning
|
||||||
|
|
@ -389,11 +430,11 @@ func typenames(t types.Type) []*types.TypeName {
|
||||||
visit(t.Params())
|
visit(t.Params())
|
||||||
visit(t.Results())
|
visit(t.Results())
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
for i := range t.NumEmbeddeds() {
|
for etyp := range t.EmbeddedTypes() {
|
||||||
visit(t.EmbeddedType(i))
|
visit(etyp)
|
||||||
}
|
}
|
||||||
for i := range t.NumExplicitMethods() {
|
for method := range t.ExplicitMethods() {
|
||||||
visit(t.ExplicitMethod(i).Type())
|
visit(method.Type())
|
||||||
}
|
}
|
||||||
case *types.Tuple:
|
case *types.Tuple:
|
||||||
for v := range t.Variables() {
|
for v := range t.Variables() {
|
||||||
2
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/inspect/inspect.go
generated
vendored
2
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/inspect/inspect.go
generated
vendored
|
|
@ -41,7 +41,7 @@ var Analyzer = &analysis.Analyzer{
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/inspect",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/inspect",
|
||||||
Run: run,
|
Run: run,
|
||||||
RunDespiteErrors: true,
|
RunDespiteErrors: true,
|
||||||
ResultType: reflect.TypeOf(new(inspector.Inspector)),
|
ResultType: reflect.TypeFor[*inspector.Inspector](),
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
func run(pass *analysis.Pass) (any, error) {
|
||||||
|
|
|
||||||
17
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/ctrlflowinternal/ctrlflowinternal.go
generated
vendored
Normal file
17
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/ctrlflowinternal/ctrlflowinternal.go
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2025 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 ctrlflowinternal exposes internals of ctrlflow.
|
||||||
|
// It cannot actually depend on symbols from ctrlflow.
|
||||||
|
package ctrlflowinternal
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
// NoReturn exposes the (*ctrlflow.CFGs).NoReturn method to the buildssa analyzer.
|
||||||
|
//
|
||||||
|
// You must link [golang.org/x/tools/go/analysis/passes/ctrlflow] into your
|
||||||
|
// application for it to be non-nil.
|
||||||
|
var NoReturn = func(cfgs any, fn *types.Func) bool {
|
||||||
|
panic("x/tools/go/analysis/passes/ctrlflow is not linked into this application")
|
||||||
|
}
|
||||||
43
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go
generated
vendored
43
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go
generated
vendored
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
"golang.org/x/tools/internal/versions"
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
@ -23,7 +23,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "loopclosure",
|
Name: "loopclosure",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "loopclosure"),
|
Doc: analyzerutil.MustExtractDoc(doc, "loopclosure"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/loopclosure",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/loopclosure",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
@ -55,8 +55,8 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
switch n := n.(type) {
|
switch n := n.(type) {
|
||||||
case *ast.File:
|
case *ast.File:
|
||||||
// Only traverse the file if its goversion is strictly before go1.22.
|
// Only traverse the file if its goversion is strictly before go1.22.
|
||||||
goversion := versions.FileVersion(pass.TypesInfo, n)
|
return !analyzerutil.FileUsesGoVersion(pass, n, versions.Go1_22)
|
||||||
return versions.Before(goversion, versions.Go1_22)
|
|
||||||
case *ast.RangeStmt:
|
case *ast.RangeStmt:
|
||||||
body = n.Body
|
body = n.Body
|
||||||
addVar(n.Key)
|
addVar(n.Key)
|
||||||
|
|
@ -308,12 +308,11 @@ func parallelSubtest(info *types.Info, call *ast.CallExpr) []ast.Stmt {
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
expr := exprStmt.X
|
call, ok := exprStmt.X.(*ast.CallExpr)
|
||||||
if isMethodCall(info, expr, "testing", "T", "Parallel") {
|
if !ok {
|
||||||
call, _ := expr.(*ast.CallExpr)
|
continue
|
||||||
if call == nil {
|
}
|
||||||
continue
|
if isMethodCall(info, call, "testing", "T", "Parallel") {
|
||||||
}
|
|
||||||
x, _ := call.Fun.(*ast.SelectorExpr)
|
x, _ := call.Fun.(*ast.SelectorExpr)
|
||||||
if x == nil {
|
if x == nil {
|
||||||
continue
|
continue
|
||||||
|
|
@ -347,26 +346,6 @@ func unlabel(stmt ast.Stmt) (ast.Stmt, bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// isMethodCall reports whether expr is a method call of
|
func isMethodCall(info *types.Info, call *ast.CallExpr, pkgPath, typeName, method string) bool {
|
||||||
// <pkgPath>.<typeName>.<method>.
|
return typesinternal.IsMethodNamed(typeutil.Callee(info, call), pkgPath, typeName, method)
|
||||||
func isMethodCall(info *types.Info, expr ast.Expr, pkgPath, typeName, method string) bool {
|
|
||||||
call, ok := expr.(*ast.CallExpr)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that we are calling a method <method>
|
|
||||||
f := typeutil.StaticCallee(info, call)
|
|
||||||
if f == nil || f.Name() != method {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
recv := f.Type().(*types.Signature).Recv()
|
|
||||||
if recv == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the receiver is a <pkgPath>.<typeName> or
|
|
||||||
// *<pkgPath>.<typeName>.
|
|
||||||
_, named := typesinternal.ReceiverNamed(recv)
|
|
||||||
return typesinternal.IsTypeNamed(named, pkgPath, typeName)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/lostcancel/lostcancel.go
generated
vendored
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/lostcancel/lostcancel.go
generated
vendored
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/cfg"
|
"golang.org/x/tools/go/cfg"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
@ -25,7 +25,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "lostcancel",
|
Name: "lostcancel",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "lostcancel"),
|
Doc: analyzerutil.MustExtractDoc(doc, "lostcancel"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/lostcancel",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/lostcancel",
|
||||||
Run: run,
|
Run: run,
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
|
|
@ -316,8 +316,8 @@ outer:
|
||||||
}
|
}
|
||||||
|
|
||||||
func tupleContains(tuple *types.Tuple, v *types.Var) bool {
|
func tupleContains(tuple *types.Tuple, v *types.Var) bool {
|
||||||
for i := 0; i < tuple.Len(); i++ {
|
for v0 := range tuple.Variables() {
|
||||||
if tuple.At(i) == v {
|
if v0 == v {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/any.go
generated
vendored
24
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/any.go
generated
vendored
|
|
@ -9,29 +9,21 @@ import (
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/versions"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var AnyAnalyzer = &analysis.Analyzer{
|
var AnyAnalyzer = &analysis.Analyzer{
|
||||||
Name: "any",
|
Name: "any",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "any"),
|
Doc: analyzerutil.MustExtractDoc(doc, "any"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
generated.Analyzer,
|
Run: runAny,
|
||||||
inspect.Analyzer,
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#any",
|
||||||
},
|
|
||||||
Run: runAny,
|
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#any",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The any pass replaces interface{} with go1.18's 'any'.
|
// The any pass replaces interface{} with go1.18's 'any'.
|
||||||
func runAny(pass *analysis.Pass) (any, error) {
|
func runAny(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_18) {
|
||||||
|
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
|
||||||
|
|
||||||
for curFile := range filesUsing(inspect, pass.TypesInfo, "go1.18") {
|
|
||||||
for curIface := range curFile.Preorder((*ast.InterfaceType)(nil)) {
|
for curIface := range curFile.Preorder((*ast.InterfaceType)(nil)) {
|
||||||
iface := curIface.Node().(*ast.InterfaceType)
|
iface := curIface.Node().(*ast.InterfaceType)
|
||||||
|
|
||||||
|
|
|
||||||
36
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/bloop.go
generated
vendored
36
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/bloop.go
generated
vendored
|
|
@ -15,20 +15,19 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/moreiters"
|
"golang.org/x/tools/internal/moreiters"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var BLoopAnalyzer = &analysis.Analyzer{
|
var BLoopAnalyzer = &analysis.Analyzer{
|
||||||
Name: "bloop",
|
Name: "bloop",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "bloop"),
|
Doc: analyzerutil.MustExtractDoc(doc, "bloop"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -45,16 +44,13 @@ var BLoopAnalyzer = &analysis.Analyzer{
|
||||||
// for i := 0; i < b.N; i++ {} => for b.Loop() {}
|
// for i := 0; i < b.N; i++ {} => for b.Loop() {}
|
||||||
// for range b.N {}
|
// for range b.N {}
|
||||||
func bloop(pass *analysis.Pass) (any, error) {
|
func bloop(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
if !typesinternal.Imports(pass.Pkg, "testing") {
|
if !typesinternal.Imports(pass.Pkg, "testing") {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
inspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
info = pass.TypesInfo
|
||||||
info = pass.TypesInfo
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// edits computes the text edits for a matched for/range loop
|
// edits computes the text edits for a matched for/range loop
|
||||||
|
|
@ -102,7 +98,7 @@ func bloop(pass *analysis.Pass) (any, error) {
|
||||||
(*ast.ForStmt)(nil),
|
(*ast.ForStmt)(nil),
|
||||||
(*ast.RangeStmt)(nil),
|
(*ast.RangeStmt)(nil),
|
||||||
}
|
}
|
||||||
for curFile := range filesUsing(inspect, info, "go1.24") {
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_24) {
|
||||||
for curLoop := range curFile.Preorder(loops...) {
|
for curLoop := range curFile.Preorder(loops...) {
|
||||||
switch n := curLoop.Node().(type) {
|
switch n := curLoop.Node().(type) {
|
||||||
case *ast.ForStmt:
|
case *ast.ForStmt:
|
||||||
|
|
@ -189,6 +185,7 @@ func enclosingFunc(c inspector.Cursor) (inspector.Cursor, bool) {
|
||||||
// 2. The only b.N loop in that benchmark function
|
// 2. The only b.N loop in that benchmark function
|
||||||
// - b.Loop() can only be called once per benchmark execution
|
// - b.Loop() can only be called once per benchmark execution
|
||||||
// - Multiple calls result in "B.Loop called with timer stopped" error
|
// - Multiple calls result in "B.Loop called with timer stopped" error
|
||||||
|
// - Multiple loops may have complex interdependencies that are hard to analyze
|
||||||
func usesBenchmarkNOnce(c inspector.Cursor, info *types.Info) bool {
|
func usesBenchmarkNOnce(c inspector.Cursor, info *types.Info) bool {
|
||||||
// Find the enclosing benchmark function
|
// Find the enclosing benchmark function
|
||||||
curFunc, ok := enclosingFunc(c)
|
curFunc, ok := enclosingFunc(c)
|
||||||
|
|
@ -205,17 +202,14 @@ func usesBenchmarkNOnce(c inspector.Cursor, info *types.Info) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count b.N references in this benchmark function
|
// Count all b.N references in this benchmark function (including nested functions)
|
||||||
bnRefCount := 0
|
bnRefCount := 0
|
||||||
filter := []ast.Node{(*ast.SelectorExpr)(nil), (*ast.FuncLit)(nil)}
|
filter := []ast.Node{(*ast.SelectorExpr)(nil)}
|
||||||
curFunc.Inspect(filter, func(cur inspector.Cursor) bool {
|
curFunc.Inspect(filter, func(cur inspector.Cursor) bool {
|
||||||
switch n := cur.Node().(type) {
|
sel := cur.Node().(*ast.SelectorExpr)
|
||||||
case *ast.FuncLit:
|
if sel.Sel.Name == "N" &&
|
||||||
return false // don't descend into nested function literals
|
typesinternal.IsPointerToNamed(info.TypeOf(sel.X), "testing", "B") {
|
||||||
case *ast.SelectorExpr:
|
bnRefCount++
|
||||||
if n.Sel.Name == "N" && typesinternal.IsPointerToNamed(info.TypeOf(n.X), "testing", "B") {
|
|
||||||
bnRefCount++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
@ -240,7 +234,7 @@ func isIncrementLoop(info *types.Info, loop *ast.ForStmt) *types.Var {
|
||||||
if assign, ok := loop.Init.(*ast.AssignStmt); ok &&
|
if assign, ok := loop.Init.(*ast.AssignStmt); ok &&
|
||||||
assign.Tok == token.DEFINE &&
|
assign.Tok == token.DEFINE &&
|
||||||
len(assign.Rhs) == 1 &&
|
len(assign.Rhs) == 1 &&
|
||||||
isZeroIntLiteral(info, assign.Rhs[0]) &&
|
isZeroIntConst(info, assign.Rhs[0]) &&
|
||||||
is[*ast.IncDecStmt](loop.Post) &&
|
is[*ast.IncDecStmt](loop.Post) &&
|
||||||
loop.Post.(*ast.IncDecStmt).Tok == token.INC &&
|
loop.Post.(*ast.IncDecStmt).Tok == token.INC &&
|
||||||
astutil.EqualSyntax(loop.Post.(*ast.IncDecStmt).X, assign.Lhs[0]) {
|
astutil.EqualSyntax(loop.Post.(*ast.IncDecStmt).X, assign.Lhs[0]) {
|
||||||
|
|
|
||||||
46
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/doc.go
generated
vendored
46
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/doc.go
generated
vendored
|
|
@ -176,8 +176,12 @@ This analyzer finds declarations of functions of this form:
|
||||||
and suggests a fix to turn them into inlinable wrappers around
|
and suggests a fix to turn them into inlinable wrappers around
|
||||||
go1.26's built-in new(expr) function:
|
go1.26's built-in new(expr) function:
|
||||||
|
|
||||||
|
//go:fix inline
|
||||||
func varOf(x int) *int { return new(x) }
|
func varOf(x int) *int { return new(x) }
|
||||||
|
|
||||||
|
(The directive comment causes the 'inline' analyzer to suggest
|
||||||
|
that calls to such functions are inlined.)
|
||||||
|
|
||||||
In addition, this analyzer suggests a fix for each call
|
In addition, this analyzer suggests a fix for each call
|
||||||
to one of the functions before it is transformed, so that
|
to one of the functions before it is transformed, so that
|
||||||
|
|
||||||
|
|
@ -187,9 +191,9 @@ is replaced by:
|
||||||
|
|
||||||
use(new(123))
|
use(new(123))
|
||||||
|
|
||||||
(Wrapper functions such as varOf are common when working with Go
|
Wrapper functions such as varOf are common when working with Go
|
||||||
serialization packages such as for JSON or protobuf, where pointers
|
serialization packages such as for JSON or protobuf, where pointers
|
||||||
are often used to express optionality.)
|
are often used to express optionality.
|
||||||
|
|
||||||
# Analyzer omitzero
|
# Analyzer omitzero
|
||||||
|
|
||||||
|
|
@ -327,6 +331,44 @@ iterator offered by the same data type:
|
||||||
|
|
||||||
where x is one of various well-known types in the standard library.
|
where x is one of various well-known types in the standard library.
|
||||||
|
|
||||||
|
# Analyzer stringscut
|
||||||
|
|
||||||
|
stringscut: replace strings.Index etc. with strings.Cut
|
||||||
|
|
||||||
|
This analyzer replaces certain patterns of use of [strings.Index] and string slicing by [strings.Cut], added in go1.18.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
idx := strings.Index(s, substr)
|
||||||
|
if idx >= 0 {
|
||||||
|
return s[:idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
is replaced by:
|
||||||
|
|
||||||
|
before, _, ok := strings.Cut(s, substr)
|
||||||
|
if ok {
|
||||||
|
return before
|
||||||
|
}
|
||||||
|
|
||||||
|
And:
|
||||||
|
|
||||||
|
idx := strings.Index(s, substr)
|
||||||
|
if idx >= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
is replaced by:
|
||||||
|
|
||||||
|
found := strings.Contains(s, substr)
|
||||||
|
if found {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
It also handles variants using [strings.IndexByte] instead of Index, or the bytes package instead of strings.
|
||||||
|
|
||||||
|
Fixes are offered only in cases in which there are no potential modifications of the idx, s, or substr expressions between their definition and use.
|
||||||
|
|
||||||
# Analyzer stringscutprefix
|
# Analyzer stringscutprefix
|
||||||
|
|
||||||
stringscutprefix: replace HasPrefix/TrimPrefix with CutPrefix
|
stringscutprefix: replace HasPrefix/TrimPrefix with CutPrefix
|
||||||
|
|
|
||||||
16
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/errorsastype.go
generated
vendored
16
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/errorsastype.go
generated
vendored
|
|
@ -14,21 +14,21 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/goplsexport"
|
"golang.org/x/tools/internal/goplsexport"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errorsastypeAnalyzer = &analysis.Analyzer{
|
var errorsastypeAnalyzer = &analysis.Analyzer{
|
||||||
Name: "errorsastype",
|
Name: "errorsastype",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "errorsastype"),
|
Doc: analyzerutil.MustExtractDoc(doc, "errorsastype"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#errorsastype",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#errorsastype",
|
||||||
Requires: []*analysis.Analyzer{generated.Analyzer, typeindexanalyzer.Analyzer},
|
Requires: []*analysis.Analyzer{typeindexanalyzer.Analyzer},
|
||||||
Run: errorsastype,
|
Run: errorsastype,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,8 +78,6 @@ func init() {
|
||||||
//
|
//
|
||||||
// - if errors.As(err, myerr) && othercond { ... }
|
// - if errors.As(err, myerr) && othercond { ... }
|
||||||
func errorsastype(pass *analysis.Pass) (any, error) {
|
func errorsastype(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
info = pass.TypesInfo
|
info = pass.TypesInfo
|
||||||
|
|
@ -97,7 +95,7 @@ func errorsastype(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
file := astutil.EnclosingFile(curDeclStmt)
|
file := astutil.EnclosingFile(curDeclStmt)
|
||||||
if !fileUses(info, file, "go1.26") {
|
if !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_26) {
|
||||||
continue // errors.AsType is too new
|
continue // errors.AsType is too new
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,6 +125,8 @@ func errorsastype(pass *analysis.Pass) (any, error) {
|
||||||
errtype := types.TypeString(v.Type(), qual)
|
errtype := types.TypeString(v.Type(), qual)
|
||||||
|
|
||||||
// Choose a name for the "ok" variable.
|
// Choose a name for the "ok" variable.
|
||||||
|
// TODO(adonovan): this pattern also appears in stditerators,
|
||||||
|
// and is wanted elsewhere; factor.
|
||||||
okName := "ok"
|
okName := "ok"
|
||||||
if okVar := lookup(info, curCall, "ok"); okVar != nil {
|
if okVar := lookup(info, curCall, "ok"); okVar != nil {
|
||||||
// The name 'ok' is already declared, but
|
// The name 'ok' is already declared, but
|
||||||
|
|
|
||||||
13
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/fmtappendf.go
generated
vendored
13
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/fmtappendf.go
generated
vendored
|
|
@ -13,18 +13,17 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var FmtAppendfAnalyzer = &analysis.Analyzer{
|
var FmtAppendfAnalyzer = &analysis.Analyzer{
|
||||||
Name: "fmtappendf",
|
Name: "fmtappendf",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "fmtappendf"),
|
Doc: analyzerutil.MustExtractDoc(doc, "fmtappendf"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -35,8 +34,6 @@ var FmtAppendfAnalyzer = &analysis.Analyzer{
|
||||||
// The fmtappend function replaces []byte(fmt.Sprintf(...)) by
|
// The fmtappend function replaces []byte(fmt.Sprintf(...)) by
|
||||||
// fmt.Appendf(nil, ...), and similarly for Sprint, Sprintln.
|
// fmt.Appendf(nil, ...), and similarly for Sprint, Sprintln.
|
||||||
func fmtappendf(pass *analysis.Pass) (any, error) {
|
func fmtappendf(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
index := pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
index := pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
for _, fn := range []types.Object{
|
for _, fn := range []types.Object{
|
||||||
index.Object("fmt", "Sprintf"),
|
index.Object("fmt", "Sprintf"),
|
||||||
|
|
@ -50,7 +47,7 @@ func fmtappendf(pass *analysis.Pass) (any, error) {
|
||||||
conv := curCall.Parent().Node().(*ast.CallExpr)
|
conv := curCall.Parent().Node().(*ast.CallExpr)
|
||||||
tv := pass.TypesInfo.Types[conv.Fun]
|
tv := pass.TypesInfo.Types[conv.Fun]
|
||||||
if tv.IsType() && types.Identical(tv.Type, byteSliceType) &&
|
if tv.IsType() && types.Identical(tv.Type, byteSliceType) &&
|
||||||
fileUses(pass.TypesInfo, astutil.EnclosingFile(curCall), "go1.19") {
|
analyzerutil.FileUsesGoVersion(pass, astutil.EnclosingFile(curCall), versions.Go1_19) {
|
||||||
// Have: []byte(fmt.SprintX(...))
|
// Have: []byte(fmt.SprintX(...))
|
||||||
|
|
||||||
// Find "Sprint" identifier.
|
// Find "Sprint" identifier.
|
||||||
|
|
|
||||||
99
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/forvar.go
generated
vendored
99
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/forvar.go
generated
vendored
|
|
@ -10,22 +10,18 @@ import (
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ForVarAnalyzer = &analysis.Analyzer{
|
var ForVarAnalyzer = &analysis.Analyzer{
|
||||||
Name: "forvar",
|
Name: "forvar",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "forvar"),
|
Doc: analyzerutil.MustExtractDoc(doc, "forvar"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
generated.Analyzer,
|
Run: forvar,
|
||||||
inspect.Analyzer,
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#forvar",
|
||||||
},
|
|
||||||
Run: forvar,
|
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#forvar",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// forvar offers to fix unnecessary copying of a for variable
|
// forvar offers to fix unnecessary copying of a for variable
|
||||||
|
|
@ -39,54 +35,77 @@ var ForVarAnalyzer = &analysis.Analyzer{
|
||||||
// where the two idents are the same,
|
// where the two idents are the same,
|
||||||
// and the ident is defined (:=) as a variable in the for statement.
|
// and the ident is defined (:=) as a variable in the for statement.
|
||||||
// (Note that this 'fix' does not work for three clause loops
|
// (Note that this 'fix' does not work for three clause loops
|
||||||
// because the Go specification says "The variable used by each subsequent iteration
|
// because the Go specfilesUsingGoVersionsays "The variable used by each subsequent iteration
|
||||||
// is declared implicitly before executing the post statement and initialized to the
|
// is declared implicitly before executing the post statement and initialized to the
|
||||||
// value of the previous iteration's variable at that moment.")
|
// value of the previous iteration's variable at that moment.")
|
||||||
|
//
|
||||||
|
// Variant: same thing in an IfStmt.Init, when the IfStmt is the sole
|
||||||
|
// loop body statement:
|
||||||
|
//
|
||||||
|
// for _, x := range foo {
|
||||||
|
// if x := x; cond { ... }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// (The restriction is necessary to avoid potential problems arising
|
||||||
|
// from merging two distinct variables.)
|
||||||
|
//
|
||||||
|
// This analyzer is synergistic with stditerators,
|
||||||
|
// which may create redundant "x := x" statements.
|
||||||
func forvar(pass *analysis.Pass) (any, error) {
|
func forvar(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_22) {
|
||||||
|
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
|
||||||
for curFile := range filesUsing(inspect, pass.TypesInfo, "go1.22") {
|
|
||||||
for curLoop := range curFile.Preorder((*ast.RangeStmt)(nil)) {
|
for curLoop := range curFile.Preorder((*ast.RangeStmt)(nil)) {
|
||||||
loop := curLoop.Node().(*ast.RangeStmt)
|
loop := curLoop.Node().(*ast.RangeStmt)
|
||||||
if loop.Tok != token.DEFINE {
|
if loop.Tok != token.DEFINE {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
isLoopVarRedecl := func(assign *ast.AssignStmt) bool {
|
isLoopVarRedecl := func(stmt ast.Stmt) bool {
|
||||||
for i, lhs := range assign.Lhs {
|
if assign, ok := stmt.(*ast.AssignStmt); ok &&
|
||||||
if !(astutil.EqualSyntax(lhs, assign.Rhs[i]) &&
|
assign.Tok == token.DEFINE &&
|
||||||
(astutil.EqualSyntax(lhs, loop.Key) || astutil.EqualSyntax(lhs, loop.Value))) {
|
len(assign.Lhs) == len(assign.Rhs) {
|
||||||
return false
|
|
||||||
|
for i, lhs := range assign.Lhs {
|
||||||
|
if !(astutil.EqualSyntax(lhs, assign.Rhs[i]) &&
|
||||||
|
(astutil.EqualSyntax(lhs, loop.Key) ||
|
||||||
|
astutil.EqualSyntax(lhs, loop.Value))) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
// Have: for k, v := range x { stmts }
|
// Have: for k, v := range x { stmts }
|
||||||
//
|
//
|
||||||
// Delete the prefix of stmts that are
|
// Delete the prefix of stmts that are
|
||||||
// of the form k := k; v := v; k, v := k, v; v, k := v, k.
|
// of the form k := k; v := v; k, v := k, v; v, k := v, k.
|
||||||
for _, stmt := range loop.Body.List {
|
for _, stmt := range loop.Body.List {
|
||||||
if assign, ok := stmt.(*ast.AssignStmt); ok &&
|
if isLoopVarRedecl(stmt) {
|
||||||
assign.Tok == token.DEFINE &&
|
// { x := x; ... }
|
||||||
len(assign.Lhs) == len(assign.Rhs) &&
|
// ------
|
||||||
isLoopVarRedecl(assign) {
|
} else if ifstmt, ok := stmt.(*ast.IfStmt); ok &&
|
||||||
|
ifstmt.Init != nil &&
|
||||||
curStmt, _ := curLoop.FindNode(stmt)
|
len(loop.Body.List) == 1 && // must be sole statement in loop body
|
||||||
edits := refactor.DeleteStmt(pass.Fset.File(stmt.Pos()), curStmt)
|
isLoopVarRedecl(ifstmt.Init) {
|
||||||
if len(edits) > 0 {
|
// if x := x; cond {
|
||||||
pass.Report(analysis.Diagnostic{
|
// ------
|
||||||
Pos: stmt.Pos(),
|
stmt = ifstmt.Init
|
||||||
End: stmt.End(),
|
|
||||||
Message: "copying variable is unneeded",
|
|
||||||
SuggestedFixes: []analysis.SuggestedFix{{
|
|
||||||
Message: "Remove unneeded redeclaration",
|
|
||||||
TextEdits: edits,
|
|
||||||
}},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
break // stop at first other statement
|
break // stop at first other statement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curStmt, _ := curLoop.FindNode(stmt)
|
||||||
|
edits := refactor.DeleteStmt(pass.Fset.File(stmt.Pos()), curStmt)
|
||||||
|
if len(edits) > 0 {
|
||||||
|
pass.Report(analysis.Diagnostic{
|
||||||
|
Pos: stmt.Pos(),
|
||||||
|
End: stmt.End(),
|
||||||
|
Message: "copying variable is unneeded",
|
||||||
|
SuggestedFixes: []analysis.SuggestedFix{{
|
||||||
|
Message: "Remove unneeded redeclaration",
|
||||||
|
TextEdits: edits,
|
||||||
|
}},
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/maps.go
generated
vendored
22
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/maps.go
generated
vendored
|
|
@ -15,23 +15,20 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typeparams"
|
"golang.org/x/tools/internal/typeparams"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var MapsLoopAnalyzer = &analysis.Analyzer{
|
var MapsLoopAnalyzer = &analysis.Analyzer{
|
||||||
Name: "mapsloop",
|
Name: "mapsloop",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "mapsloop"),
|
Doc: analyzerutil.MustExtractDoc(doc, "mapsloop"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
generated.Analyzer,
|
Run: mapsloop,
|
||||||
inspect.Analyzer,
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#mapsloop",
|
||||||
},
|
|
||||||
Run: mapsloop,
|
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#mapsloop",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The mapsloop pass offers to simplify a loop of map insertions:
|
// The mapsloop pass offers to simplify a loop of map insertions:
|
||||||
|
|
@ -55,8 +52,6 @@ var MapsLoopAnalyzer = &analysis.Analyzer{
|
||||||
// m = make(M)
|
// m = make(M)
|
||||||
// m = M{}
|
// m = M{}
|
||||||
func mapsloop(pass *analysis.Pass) (any, error) {
|
func mapsloop(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
// Skip the analyzer in packages where its
|
// Skip the analyzer in packages where its
|
||||||
// fixes would create an import cycle.
|
// fixes would create an import cycle.
|
||||||
if within(pass, "maps", "bytes", "runtime") {
|
if within(pass, "maps", "bytes", "runtime") {
|
||||||
|
|
@ -223,8 +218,7 @@ func mapsloop(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find all range loops around m[k] = v.
|
// Find all range loops around m[k] = v.
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_23) {
|
||||||
for curFile := range filesUsing(inspect, pass.TypesInfo, "go1.23") {
|
|
||||||
file := curFile.Node().(*ast.File)
|
file := curFile.Node().(*ast.File)
|
||||||
|
|
||||||
for curRange := range curFile.Preorder((*ast.RangeStmt)(nil)) {
|
for curRange := range curFile.Preorder((*ast.RangeStmt)(nil)) {
|
||||||
|
|
|
||||||
14
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/minmax.go
generated
vendored
14
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/minmax.go
generated
vendored
|
|
@ -15,19 +15,18 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/typeparams"
|
"golang.org/x/tools/internal/typeparams"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var MinMaxAnalyzer = &analysis.Analyzer{
|
var MinMaxAnalyzer = &analysis.Analyzer{
|
||||||
Name: "minmax",
|
Name: "minmax",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "minmax"),
|
Doc: analyzerutil.MustExtractDoc(doc, "minmax"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -56,8 +55,6 @@ var MinMaxAnalyzer = &analysis.Analyzer{
|
||||||
// - "x := a" or "x = a" or "var x = a" in pattern 2
|
// - "x := a" or "x = a" or "var x = a" in pattern 2
|
||||||
// - "x < b" or "a < b" in pattern 2
|
// - "x < b" or "a < b" in pattern 2
|
||||||
func minmax(pass *analysis.Pass) (any, error) {
|
func minmax(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
// Check for user-defined min/max functions that can be removed
|
// Check for user-defined min/max functions that can be removed
|
||||||
checkUserDefinedMinMax(pass)
|
checkUserDefinedMinMax(pass)
|
||||||
|
|
||||||
|
|
@ -201,8 +198,7 @@ func minmax(pass *analysis.Pass) (any, error) {
|
||||||
|
|
||||||
// Find all "if a < b { lhs = rhs }" statements.
|
// Find all "if a < b { lhs = rhs }" statements.
|
||||||
info := pass.TypesInfo
|
info := pass.TypesInfo
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_21) {
|
||||||
for curFile := range filesUsing(inspect, info, "go1.21") {
|
|
||||||
astFile := curFile.Node().(*ast.File)
|
astFile := curFile.Node().(*ast.File)
|
||||||
for curIfStmt := range curFile.Preorder((*ast.IfStmt)(nil)) {
|
for curIfStmt := range curFile.Preorder((*ast.IfStmt)(nil)) {
|
||||||
ifStmt := curIfStmt.Node().(*ast.IfStmt)
|
ifStmt := curIfStmt.Node().(*ast.IfStmt)
|
||||||
|
|
|
||||||
49
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/modernize.go
generated
vendored
49
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/modernize.go
generated
vendored
|
|
@ -16,15 +16,15 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/moreiters"
|
"golang.org/x/tools/internal/moreiters"
|
||||||
"golang.org/x/tools/internal/packagepath"
|
"golang.org/x/tools/internal/packagepath"
|
||||||
"golang.org/x/tools/internal/stdlib"
|
"golang.org/x/tools/internal/stdlib"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
"golang.org/x/tools/internal/versions"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -48,6 +48,7 @@ var Suite = []*analysis.Analyzer{
|
||||||
// SlicesDeleteAnalyzer, // not nil-preserving!
|
// SlicesDeleteAnalyzer, // not nil-preserving!
|
||||||
SlicesSortAnalyzer,
|
SlicesSortAnalyzer,
|
||||||
stditeratorsAnalyzer,
|
stditeratorsAnalyzer,
|
||||||
|
stringscutAnalyzer,
|
||||||
StringsCutPrefixAnalyzer,
|
StringsCutPrefixAnalyzer,
|
||||||
StringsSeqAnalyzer,
|
StringsSeqAnalyzer,
|
||||||
StringsBuilderAnalyzer,
|
StringsBuilderAnalyzer,
|
||||||
|
|
@ -57,18 +58,6 @@ var Suite = []*analysis.Analyzer{
|
||||||
|
|
||||||
// -- helpers --
|
// -- helpers --
|
||||||
|
|
||||||
// skipGenerated decorates pass.Report to suppress diagnostics in generated files.
|
|
||||||
func skipGenerated(pass *analysis.Pass) {
|
|
||||||
report := pass.Report
|
|
||||||
pass.Report = func(diag analysis.Diagnostic) {
|
|
||||||
generated := pass.ResultOf[generated.Analyzer].(*generated.Result)
|
|
||||||
if generated.IsGenerated(diag.Pos) {
|
|
||||||
return // skip
|
|
||||||
}
|
|
||||||
report(diag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// formatExprs formats a comma-separated list of expressions.
|
// formatExprs formats a comma-separated list of expressions.
|
||||||
func formatExprs(fset *token.FileSet, exprs []ast.Expr) string {
|
func formatExprs(fset *token.FileSet, exprs []ast.Expr) string {
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
|
|
@ -81,8 +70,8 @@ func formatExprs(fset *token.FileSet, exprs []ast.Expr) string {
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// isZeroIntLiteral reports whether e is an integer whose value is 0.
|
// isZeroIntConst reports whether e is an integer whose value is 0.
|
||||||
func isZeroIntLiteral(info *types.Info, e ast.Expr) bool {
|
func isZeroIntConst(info *types.Info, e ast.Expr) bool {
|
||||||
return isIntLiteral(info, e, 0)
|
return isIntLiteral(info, e, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,36 +80,28 @@ func isIntLiteral(info *types.Info, e ast.Expr, n int64) bool {
|
||||||
return info.Types[e].Value == constant.MakeInt64(n)
|
return info.Types[e].Value == constant.MakeInt64(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// filesUsing returns a cursor for each *ast.File in the inspector
|
// filesUsingGoVersion returns a cursor for each *ast.File in the inspector
|
||||||
// that uses at least the specified version of Go (e.g. "go1.24").
|
// that uses at least the specified version of Go (e.g. "go1.24").
|
||||||
//
|
//
|
||||||
|
// The pass's analyzer must require [inspect.Analyzer].
|
||||||
|
//
|
||||||
// TODO(adonovan): opt: eliminate this function, instead following the
|
// TODO(adonovan): opt: eliminate this function, instead following the
|
||||||
// approach of [fmtappendf], which uses typeindex and [fileUses].
|
// approach of [fmtappendf], which uses typeindex and
|
||||||
// See "Tip" at [fileUses] for motivation.
|
// [analyzerutil.FileUsesGoVersion]; see "Tip" documented at the
|
||||||
func filesUsing(inspect *inspector.Inspector, info *types.Info, version string) iter.Seq[inspector.Cursor] {
|
// latter function for motivation.
|
||||||
|
func filesUsingGoVersion(pass *analysis.Pass, version string) iter.Seq[inspector.Cursor] {
|
||||||
|
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||||
|
|
||||||
return func(yield func(inspector.Cursor) bool) {
|
return func(yield func(inspector.Cursor) bool) {
|
||||||
for curFile := range inspect.Root().Children() {
|
for curFile := range inspect.Root().Children() {
|
||||||
file := curFile.Node().(*ast.File)
|
file := curFile.Node().(*ast.File)
|
||||||
if !versions.Before(info.FileVersions[file], version) && !yield(curFile) {
|
if analyzerutil.FileUsesGoVersion(pass, file, version) && !yield(curFile) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fileUses reports whether the specified file uses at least the
|
|
||||||
// specified version of Go (e.g. "go1.24").
|
|
||||||
//
|
|
||||||
// Tip: we recommend using this check "late", just before calling
|
|
||||||
// pass.Report, rather than "early" (when entering each ast.File, or
|
|
||||||
// each candidate node of interest, during the traversal), because the
|
|
||||||
// operation is not free, yet is not a highly selective filter: the
|
|
||||||
// fraction of files that pass most version checks is high and
|
|
||||||
// increases over time.
|
|
||||||
func fileUses(info *types.Info, file *ast.File, version string) bool {
|
|
||||||
return !versions.Before(info.FileVersions[file], version)
|
|
||||||
}
|
|
||||||
|
|
||||||
// within reports whether the current pass is analyzing one of the
|
// within reports whether the current pass is analyzing one of the
|
||||||
// specified standard packages or their dependencies.
|
// specified standard packages or their dependencies.
|
||||||
func within(pass *analysis.Pass, pkgs ...string) bool {
|
func within(pass *analysis.Pass, pkgs ...string) bool {
|
||||||
|
|
|
||||||
38
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/newexpr.go
generated
vendored
38
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/newexpr.go
generated
vendored
|
|
@ -17,13 +17,14 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var NewExprAnalyzer = &analysis.Analyzer{
|
var NewExprAnalyzer = &analysis.Analyzer{
|
||||||
Name: "newexpr",
|
Name: "newexpr",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "newexpr"),
|
Doc: analyzerutil.MustExtractDoc(doc, "newexpr"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/modernize#newexpr",
|
URL: "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/modernize#newexpr",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
@ -60,7 +61,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
|
|
||||||
// Check file version.
|
// Check file version.
|
||||||
file := astutil.EnclosingFile(curFuncDecl)
|
file := astutil.EnclosingFile(curFuncDecl)
|
||||||
if !fileUses(info, file, "go1.26") {
|
if !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_26) {
|
||||||
continue // new(expr) not available in this file
|
continue // new(expr) not available in this file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,25 +88,18 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disabled until we resolve https://go.dev/issue/75726
|
// Add a //go:fix inline annotation, if not already present.
|
||||||
// (Go version skew between caller and callee in inliner.)
|
|
||||||
// TODO(adonovan): fix and reenable.
|
|
||||||
//
|
//
|
||||||
// Also, restore these lines to our section of doc.go:
|
// The inliner will not inline a newer callee body into an
|
||||||
// //go:fix inline
|
// older Go file; see https://go.dev/issue/75726.
|
||||||
// ...
|
//
|
||||||
// (The directive comment causes the inline analyzer to suggest
|
// TODO(adonovan): use ast.ParseDirective when go1.26 is assured.
|
||||||
// that calls to such functions are inlined.)
|
if !strings.Contains(decl.Doc.Text(), "go:fix inline") {
|
||||||
if false {
|
edits = append(edits, analysis.TextEdit{
|
||||||
// Add a //go:fix inline annotation, if not already present.
|
Pos: decl.Pos(),
|
||||||
// TODO(adonovan): use ast.ParseDirective when go1.26 is assured.
|
End: decl.Pos(),
|
||||||
if !strings.Contains(decl.Doc.Text(), "go:fix inline") {
|
NewText: []byte("//go:fix inline\n"),
|
||||||
edits = append(edits, analysis.TextEdit{
|
})
|
||||||
Pos: decl.Pos(),
|
|
||||||
End: decl.Pos(),
|
|
||||||
NewText: []byte("//go:fix inline\n"),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(edits) > 0 {
|
if len(edits) > 0 {
|
||||||
|
|
@ -140,7 +134,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
|
|
||||||
// Check file version.
|
// Check file version.
|
||||||
file := astutil.EnclosingFile(curCall)
|
file := astutil.EnclosingFile(curCall)
|
||||||
if !fileUses(info, file, "go1.26") {
|
if !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_26) {
|
||||||
continue // new(expr) not available in this file
|
continue // new(expr) not available in this file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
49
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/omitzero.go
generated
vendored
49
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/omitzero.go
generated
vendored
|
|
@ -12,21 +12,17 @@ import (
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var OmitZeroAnalyzer = &analysis.Analyzer{
|
var OmitZeroAnalyzer = &analysis.Analyzer{
|
||||||
Name: "omitzero",
|
Name: "omitzero",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "omitzero"),
|
Doc: analyzerutil.MustExtractDoc(doc, "omitzero"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
generated.Analyzer,
|
Run: omitzero,
|
||||||
inspect.Analyzer,
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#omitzero",
|
||||||
},
|
|
||||||
Run: omitzero,
|
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#omitzero",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkOmitEmptyField(pass *analysis.Pass, info *types.Info, curField *ast.Field) {
|
func checkOmitEmptyField(pass *analysis.Pass, info *types.Info, curField *ast.Field) {
|
||||||
|
|
@ -48,25 +44,20 @@ func checkOmitEmptyField(pass *analysis.Pass, info *types.Info, curField *ast.Fi
|
||||||
// No omitempty in json tag
|
// No omitempty in json tag
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
omitEmptyPos, omitEmptyEnd, err := astutil.RangeInStringLiteral(curField.Tag, match[2], match[3])
|
omitEmpty, err := astutil.RangeInStringLiteral(curField.Tag, match[2], match[3])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
removePos, removeEnd := omitEmptyPos, omitEmptyEnd
|
var remove analysis.Range = omitEmpty
|
||||||
|
|
||||||
jsonTag := reflect.StructTag(tagconv).Get("json")
|
jsonTag := reflect.StructTag(tagconv).Get("json")
|
||||||
if jsonTag == ",omitempty" {
|
if jsonTag == ",omitempty" {
|
||||||
// Remove the entire struct tag if json is the only package used
|
// Remove the entire struct tag if json is the only package used
|
||||||
if match[1]-match[0] == len(tagconv) {
|
if match[1]-match[0] == len(tagconv) {
|
||||||
removePos = curField.Tag.Pos()
|
remove = curField.Tag
|
||||||
removeEnd = curField.Tag.End()
|
|
||||||
} else {
|
} else {
|
||||||
// Remove the json tag if omitempty is the only field
|
// Remove the json tag if omitempty is the only field
|
||||||
removePos, err = astutil.PosInStringLiteral(curField.Tag, match[0])
|
remove, err = astutil.RangeInStringLiteral(curField.Tag, match[0], match[1])
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
removeEnd, err = astutil.PosInStringLiteral(curField.Tag, match[1])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -81,8 +72,8 @@ func checkOmitEmptyField(pass *analysis.Pass, info *types.Info, curField *ast.Fi
|
||||||
Message: "Remove redundant omitempty tag",
|
Message: "Remove redundant omitempty tag",
|
||||||
TextEdits: []analysis.TextEdit{
|
TextEdits: []analysis.TextEdit{
|
||||||
{
|
{
|
||||||
Pos: removePos,
|
Pos: remove.Pos(),
|
||||||
End: removeEnd,
|
End: remove.End(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -90,8 +81,8 @@ func checkOmitEmptyField(pass *analysis.Pass, info *types.Info, curField *ast.Fi
|
||||||
Message: "Replace omitempty with omitzero (behavior change)",
|
Message: "Replace omitempty with omitzero (behavior change)",
|
||||||
TextEdits: []analysis.TextEdit{
|
TextEdits: []analysis.TextEdit{
|
||||||
{
|
{
|
||||||
Pos: omitEmptyPos,
|
Pos: omitEmpty.Pos(),
|
||||||
End: omitEmptyEnd,
|
End: omitEmpty.End(),
|
||||||
NewText: []byte(",omitzero"),
|
NewText: []byte(",omitzero"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -100,18 +91,14 @@ func checkOmitEmptyField(pass *analysis.Pass, info *types.Info, curField *ast.Fi
|
||||||
}
|
}
|
||||||
|
|
||||||
// The omitzero pass searches for instances of "omitempty" in a json field tag on a
|
// The omitzero pass searches for instances of "omitempty" in a json field tag on a
|
||||||
// struct. Since "omitempty" does not have any effect when applied to a struct field,
|
// struct. Since "omitfilesUsingGoVersions not have any effect when applied to a struct field,
|
||||||
// it suggests either deleting "omitempty" or replacing it with "omitzero", which
|
// it suggests either deleting "omitempty" or replacing it with "omitzero", which
|
||||||
// correctly excludes structs from a json encoding.
|
// correctly excludes structs from a json encoding.
|
||||||
func omitzero(pass *analysis.Pass) (any, error) {
|
func omitzero(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_24) {
|
||||||
|
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
|
||||||
info := pass.TypesInfo
|
|
||||||
for curFile := range filesUsing(inspect, info, "go1.24") {
|
|
||||||
for curStruct := range curFile.Preorder((*ast.StructType)(nil)) {
|
for curStruct := range curFile.Preorder((*ast.StructType)(nil)) {
|
||||||
for _, curField := range curStruct.Node().(*ast.StructType).Fields.List {
|
for _, curField := range curStruct.Node().(*ast.StructType).Fields.List {
|
||||||
checkOmitEmptyField(pass, info, curField)
|
checkOmitEmptyField(pass, pass.TypesInfo, curField)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
7
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/plusbuild.go
generated
vendored
7
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/plusbuild.go
generated
vendored
|
|
@ -10,13 +10,14 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/goplsexport"
|
"golang.org/x/tools/internal/goplsexport"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var plusBuildAnalyzer = &analysis.Analyzer{
|
var plusBuildAnalyzer = &analysis.Analyzer{
|
||||||
Name: "plusbuild",
|
Name: "plusbuild",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "plusbuild"),
|
Doc: analyzerutil.MustExtractDoc(doc, "plusbuild"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#plusbuild",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#plusbuild",
|
||||||
Run: plusbuild,
|
Run: plusbuild,
|
||||||
}
|
}
|
||||||
|
|
@ -28,7 +29,7 @@ func init() {
|
||||||
|
|
||||||
func plusbuild(pass *analysis.Pass) (any, error) {
|
func plusbuild(pass *analysis.Pass) (any, error) {
|
||||||
check := func(f *ast.File) {
|
check := func(f *ast.File) {
|
||||||
if !fileUses(pass.TypesInfo, f, "go1.18") {
|
if !analyzerutil.FileUsesGoVersion(pass, f, versions.Go1_18) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
23
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/rangeint.go
generated
vendored
23
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/rangeint.go
generated
vendored
|
|
@ -15,19 +15,18 @@ import (
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var RangeIntAnalyzer = &analysis.Analyzer{
|
var RangeIntAnalyzer = &analysis.Analyzer{
|
||||||
Name: "rangeint",
|
Name: "rangeint",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "rangeint"),
|
Doc: analyzerutil.MustExtractDoc(doc, "rangeint"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -66,21 +65,19 @@ var RangeIntAnalyzer = &analysis.Analyzer{
|
||||||
// - a constant; or
|
// - a constant; or
|
||||||
// - len(s), where s has the above properties.
|
// - len(s), where s has the above properties.
|
||||||
func rangeint(pass *analysis.Pass) (any, error) {
|
func rangeint(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
var (
|
||||||
|
info = pass.TypesInfo
|
||||||
|
typeindex = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
|
)
|
||||||
|
|
||||||
info := pass.TypesInfo
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_22) {
|
||||||
|
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
|
||||||
typeindex := pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
|
||||||
|
|
||||||
for curFile := range filesUsing(inspect, info, "go1.22") {
|
|
||||||
nextLoop:
|
nextLoop:
|
||||||
for curLoop := range curFile.Preorder((*ast.ForStmt)(nil)) {
|
for curLoop := range curFile.Preorder((*ast.ForStmt)(nil)) {
|
||||||
loop := curLoop.Node().(*ast.ForStmt)
|
loop := curLoop.Node().(*ast.ForStmt)
|
||||||
if init, ok := loop.Init.(*ast.AssignStmt); ok &&
|
if init, ok := loop.Init.(*ast.AssignStmt); ok &&
|
||||||
isSimpleAssign(init) &&
|
isSimpleAssign(init) &&
|
||||||
is[*ast.Ident](init.Lhs[0]) &&
|
is[*ast.Ident](init.Lhs[0]) &&
|
||||||
isZeroIntLiteral(info, init.Rhs[0]) {
|
isZeroIntConst(info, init.Rhs[0]) {
|
||||||
// Have: for i = 0; ... (or i := 0)
|
// Have: for i = 0; ... (or i := 0)
|
||||||
index := init.Lhs[0].(*ast.Ident)
|
index := init.Lhs[0].(*ast.Ident)
|
||||||
|
|
||||||
|
|
|
||||||
12
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/reflect.go
generated
vendored
12
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/reflect.go
generated
vendored
|
|
@ -14,9 +14,8 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
|
|
@ -26,9 +25,8 @@ import (
|
||||||
|
|
||||||
var ReflectTypeForAnalyzer = &analysis.Analyzer{
|
var ReflectTypeForAnalyzer = &analysis.Analyzer{
|
||||||
Name: "reflecttypefor",
|
Name: "reflecttypefor",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "reflecttypefor"),
|
Doc: analyzerutil.MustExtractDoc(doc, "reflecttypefor"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -37,8 +35,6 @@ var ReflectTypeForAnalyzer = &analysis.Analyzer{
|
||||||
}
|
}
|
||||||
|
|
||||||
func reflecttypefor(pass *analysis.Pass) (any, error) {
|
func reflecttypefor(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
info = pass.TypesInfo
|
info = pass.TypesInfo
|
||||||
|
|
@ -89,7 +85,7 @@ func reflecttypefor(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
file := astutil.EnclosingFile(curCall)
|
file := astutil.EnclosingFile(curCall)
|
||||||
if versions.Before(info.FileVersions[file], "go1.22") {
|
if !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_22) {
|
||||||
continue // TypeFor requires go1.22
|
continue // TypeFor requires go1.22
|
||||||
}
|
}
|
||||||
tokFile := pass.Fset.File(file.Pos())
|
tokFile := pass.Fset.File(file.Pos())
|
||||||
|
|
|
||||||
25
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/slices.go
generated
vendored
25
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/slices.go
generated
vendored
|
|
@ -13,25 +13,21 @@ import (
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Warning: this analyzer is not safe to enable by default.
|
// Warning: this analyzer is not safe to enable by default.
|
||||||
var AppendClippedAnalyzer = &analysis.Analyzer{
|
var AppendClippedAnalyzer = &analysis.Analyzer{
|
||||||
Name: "appendclipped",
|
Name: "appendclipped",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "appendclipped"),
|
Doc: analyzerutil.MustExtractDoc(doc, "appendclipped"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
generated.Analyzer,
|
Run: appendclipped,
|
||||||
inspect.Analyzer,
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#appendclipped",
|
||||||
},
|
|
||||||
Run: appendclipped,
|
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#appendclipped",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The appendclipped pass offers to simplify a tower of append calls:
|
// The appendclipped pass offers to simplify a tower of append calls:
|
||||||
|
|
@ -59,8 +55,6 @@ var AppendClippedAnalyzer = &analysis.Analyzer{
|
||||||
// The fix does not always preserve nilness the of base slice when the
|
// The fix does not always preserve nilness the of base slice when the
|
||||||
// addends (a, b, c) are all empty (see #73557).
|
// addends (a, b, c) are all empty (see #73557).
|
||||||
func appendclipped(pass *analysis.Pass) (any, error) {
|
func appendclipped(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
// Skip the analyzer in packages where its
|
// Skip the analyzer in packages where its
|
||||||
// fixes would create an import cycle.
|
// fixes would create an import cycle.
|
||||||
if within(pass, "slices", "bytes", "runtime") {
|
if within(pass, "slices", "bytes", "runtime") {
|
||||||
|
|
@ -205,8 +199,7 @@ func appendclipped(pass *analysis.Pass) (any, error) {
|
||||||
skip := make(map[*ast.CallExpr]bool)
|
skip := make(map[*ast.CallExpr]bool)
|
||||||
|
|
||||||
// Visit calls of form append(x, y...).
|
// Visit calls of form append(x, y...).
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_21) {
|
||||||
for curFile := range filesUsing(inspect, info, "go1.21") {
|
|
||||||
file := curFile.Node().(*ast.File)
|
file := curFile.Node().(*ast.File)
|
||||||
|
|
||||||
for curCall := range curFile.Preorder((*ast.CallExpr)(nil)) {
|
for curCall := range curFile.Preorder((*ast.CallExpr)(nil)) {
|
||||||
|
|
@ -266,7 +259,7 @@ func clippedSlice(info *types.Info, e ast.Expr) (res ast.Expr, empty bool) {
|
||||||
// x[:0:0], x[:len(x):len(x)], x[:k:k]
|
// x[:0:0], x[:len(x):len(x)], x[:k:k]
|
||||||
if e.Slice3 && e.High != nil && e.Max != nil && astutil.EqualSyntax(e.High, e.Max) { // x[:k:k]
|
if e.Slice3 && e.High != nil && e.Max != nil && astutil.EqualSyntax(e.High, e.Max) { // x[:k:k]
|
||||||
res = e
|
res = e
|
||||||
empty = isZeroIntLiteral(info, e.High) // x[:0:0]
|
empty = isZeroIntConst(info, e.High) // x[:0:0]
|
||||||
if call, ok := e.High.(*ast.CallExpr); ok &&
|
if call, ok := e.High.(*ast.CallExpr); ok &&
|
||||||
typeutil.Callee(info, call) == builtinLen &&
|
typeutil.Callee(info, call) == builtinLen &&
|
||||||
astutil.EqualSyntax(call.Args[0], e.X) {
|
astutil.EqualSyntax(call.Args[0], e.X) {
|
||||||
|
|
|
||||||
52
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicescontains.go
generated
vendored
52
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicescontains.go
generated
vendored
|
|
@ -14,20 +14,19 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typeparams"
|
"golang.org/x/tools/internal/typeparams"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var SlicesContainsAnalyzer = &analysis.Analyzer{
|
var SlicesContainsAnalyzer = &analysis.Analyzer{
|
||||||
Name: "slicescontains",
|
Name: "slicescontains",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "slicescontains"),
|
Doc: analyzerutil.MustExtractDoc(doc, "slicescontains"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -66,8 +65,6 @@ var SlicesContainsAnalyzer = &analysis.Analyzer{
|
||||||
// TODO(adonovan): Add a check that needle/predicate expression from
|
// TODO(adonovan): Add a check that needle/predicate expression from
|
||||||
// if-statement has no effects. Now the program behavior may change.
|
// if-statement has no effects. Now the program behavior may change.
|
||||||
func slicescontains(pass *analysis.Pass) (any, error) {
|
func slicescontains(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
// Skip the analyzer in packages where its
|
// Skip the analyzer in packages where its
|
||||||
// fixes would create an import cycle.
|
// fixes would create an import cycle.
|
||||||
if within(pass, "slices", "runtime") {
|
if within(pass, "slices", "runtime") {
|
||||||
|
|
@ -75,9 +72,8 @@ func slicescontains(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
inspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
info = pass.TypesInfo
|
||||||
info = pass.TypesInfo
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// check is called for each RangeStmt of this form:
|
// check is called for each RangeStmt of this form:
|
||||||
|
|
@ -312,7 +308,7 @@ func slicescontains(pass *analysis.Pass) (any, error) {
|
||||||
|
|
||||||
// Special case:
|
// Special case:
|
||||||
// prev="lhs = false" body={ lhs = true; break }
|
// prev="lhs = false" body={ lhs = true; break }
|
||||||
// => lhs = slices.Contains(...) (or negation)
|
// => lhs = slices.Contains(...) (or its negation)
|
||||||
if assign, ok := body.List[0].(*ast.AssignStmt); ok &&
|
if assign, ok := body.List[0].(*ast.AssignStmt); ok &&
|
||||||
len(body.List) == 2 &&
|
len(body.List) == 2 &&
|
||||||
assign.Tok == token.ASSIGN &&
|
assign.Tok == token.ASSIGN &&
|
||||||
|
|
@ -320,13 +316,12 @@ func slicescontains(pass *analysis.Pass) (any, error) {
|
||||||
len(assign.Rhs) == 1 {
|
len(assign.Rhs) == 1 {
|
||||||
|
|
||||||
// Have: body={ lhs = rhs; break }
|
// Have: body={ lhs = rhs; break }
|
||||||
|
|
||||||
if prevAssign, ok := prevStmt.(*ast.AssignStmt); ok &&
|
if prevAssign, ok := prevStmt.(*ast.AssignStmt); ok &&
|
||||||
len(prevAssign.Lhs) == 1 &&
|
len(prevAssign.Lhs) == 1 &&
|
||||||
len(prevAssign.Rhs) == 1 &&
|
len(prevAssign.Rhs) == 1 &&
|
||||||
astutil.EqualSyntax(prevAssign.Lhs[0], assign.Lhs[0]) &&
|
astutil.EqualSyntax(prevAssign.Lhs[0], assign.Lhs[0]) &&
|
||||||
is[*ast.Ident](assign.Rhs[0]) &&
|
isTrueOrFalse(info, assign.Rhs[0]) ==
|
||||||
info.Uses[assign.Rhs[0].(*ast.Ident)] == builtinTrue {
|
-isTrueOrFalse(info, prevAssign.Rhs[0]) {
|
||||||
|
|
||||||
// Have:
|
// Have:
|
||||||
// lhs = false
|
// lhs = false
|
||||||
|
|
@ -336,15 +331,14 @@ func slicescontains(pass *analysis.Pass) (any, error) {
|
||||||
//
|
//
|
||||||
// TODO(adonovan):
|
// TODO(adonovan):
|
||||||
// - support "var lhs bool = false" and variants.
|
// - support "var lhs bool = false" and variants.
|
||||||
// - support negation.
|
|
||||||
// Both these variants seem quite significant.
|
|
||||||
// - allow the break to be omitted.
|
// - allow the break to be omitted.
|
||||||
|
neg := cond(isTrueOrFalse(info, assign.Rhs[0]) < 0, "!", "")
|
||||||
report([]analysis.TextEdit{
|
report([]analysis.TextEdit{
|
||||||
// Replace "rhs" of previous assignment by slices.Contains(...)
|
// Replace "rhs" of previous assignment by [!]slices.Contains(...)
|
||||||
{
|
{
|
||||||
Pos: prevAssign.Rhs[0].Pos(),
|
Pos: prevAssign.Rhs[0].Pos(),
|
||||||
End: prevAssign.Rhs[0].End(),
|
End: prevAssign.Rhs[0].End(),
|
||||||
NewText: []byte(contains),
|
NewText: []byte(neg + contains),
|
||||||
},
|
},
|
||||||
// Delete the loop and preceding space.
|
// Delete the loop and preceding space.
|
||||||
{
|
{
|
||||||
|
|
@ -388,7 +382,7 @@ func slicescontains(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for curFile := range filesUsing(inspect, info, "go1.21") {
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_21) {
|
||||||
file := curFile.Node().(*ast.File)
|
file := curFile.Node().(*ast.File)
|
||||||
|
|
||||||
for curRange := range curFile.Preorder((*ast.RangeStmt)(nil)) {
|
for curRange := range curFile.Preorder((*ast.RangeStmt)(nil)) {
|
||||||
|
|
@ -420,13 +414,19 @@ func slicescontains(pass *analysis.Pass) (any, error) {
|
||||||
// isReturnTrueOrFalse returns nonzero if stmt returns true (+1) or false (-1).
|
// isReturnTrueOrFalse returns nonzero if stmt returns true (+1) or false (-1).
|
||||||
func isReturnTrueOrFalse(info *types.Info, stmt ast.Stmt) int {
|
func isReturnTrueOrFalse(info *types.Info, stmt ast.Stmt) int {
|
||||||
if ret, ok := stmt.(*ast.ReturnStmt); ok && len(ret.Results) == 1 {
|
if ret, ok := stmt.(*ast.ReturnStmt); ok && len(ret.Results) == 1 {
|
||||||
if id, ok := ret.Results[0].(*ast.Ident); ok {
|
return isTrueOrFalse(info, ret.Results[0])
|
||||||
switch info.Uses[id] {
|
}
|
||||||
case builtinTrue:
|
return 0
|
||||||
return +1
|
}
|
||||||
case builtinFalse:
|
|
||||||
return -1
|
// isTrueOrFalse returns nonzero if expr is literally true (+1) or false (-1).
|
||||||
}
|
func isTrueOrFalse(info *types.Info, expr ast.Expr) int {
|
||||||
|
if id, ok := expr.(*ast.Ident); ok {
|
||||||
|
switch info.Uses[id] {
|
||||||
|
case builtinTrue:
|
||||||
|
return +1
|
||||||
|
case builtinFalse:
|
||||||
|
return -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
|
|
||||||
25
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesdelete.go
generated
vendored
25
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/slicesdelete.go
generated
vendored
|
|
@ -12,24 +12,20 @@ import (
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Warning: this analyzer is not safe to enable by default (not nil-preserving).
|
// Warning: this analyzer is not safe to enable by default (not nil-preserving).
|
||||||
var SlicesDeleteAnalyzer = &analysis.Analyzer{
|
var SlicesDeleteAnalyzer = &analysis.Analyzer{
|
||||||
Name: "slicesdelete",
|
Name: "slicesdelete",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "slicesdelete"),
|
Doc: analyzerutil.MustExtractDoc(doc, "slicesdelete"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
generated.Analyzer,
|
Run: slicesdelete,
|
||||||
inspect.Analyzer,
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicesdelete",
|
||||||
},
|
|
||||||
Run: slicesdelete,
|
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicesdelete",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The slicesdelete pass attempts to replace instances of append(s[:i], s[i+k:]...)
|
// The slicesdelete pass attempts to replace instances of append(s[:i], s[i+k:]...)
|
||||||
|
|
@ -37,15 +33,12 @@ var SlicesDeleteAnalyzer = &analysis.Analyzer{
|
||||||
// Other variations that will also have suggested replacements include:
|
// Other variations that will also have suggested replacements include:
|
||||||
// append(s[:i-1], s[i:]...) and append(s[:i+k1], s[i+k2:]) where k2 > k1.
|
// append(s[:i-1], s[i:]...) and append(s[:i+k1], s[i+k2:]) where k2 > k1.
|
||||||
func slicesdelete(pass *analysis.Pass) (any, error) {
|
func slicesdelete(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
// Skip the analyzer in packages where its
|
// Skip the analyzer in packages where its
|
||||||
// fixes would create an import cycle.
|
// fixes would create an import cycle.
|
||||||
if within(pass, "slices", "runtime") {
|
if within(pass, "slices", "runtime") {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
|
||||||
info := pass.TypesInfo
|
info := pass.TypesInfo
|
||||||
report := func(file *ast.File, call *ast.CallExpr, slice1, slice2 *ast.SliceExpr) {
|
report := func(file *ast.File, call *ast.CallExpr, slice1, slice2 *ast.SliceExpr) {
|
||||||
insert := func(pos token.Pos, text string) analysis.TextEdit {
|
insert := func(pos token.Pos, text string) analysis.TextEdit {
|
||||||
|
|
@ -55,7 +48,7 @@ func slicesdelete(pass *analysis.Pass) (any, error) {
|
||||||
return types.Identical(types.Default(info.TypeOf(e)), builtinInt.Type())
|
return types.Identical(types.Default(info.TypeOf(e)), builtinInt.Type())
|
||||||
}
|
}
|
||||||
isIntShadowed := func() bool {
|
isIntShadowed := func() bool {
|
||||||
scope := pass.TypesInfo.Scopes[file].Innermost(call.Lparen)
|
scope := info.Scopes[file].Innermost(call.Lparen)
|
||||||
if _, obj := scope.LookupParent("int", call.Lparen); obj != builtinInt {
|
if _, obj := scope.LookupParent("int", call.Lparen); obj != builtinInt {
|
||||||
return true // int type is shadowed
|
return true // int type is shadowed
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +123,7 @@ func slicesdelete(pass *analysis.Pass) (any, error) {
|
||||||
}},
|
}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for curFile := range filesUsing(inspect, info, "go1.21") {
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_21) {
|
||||||
file := curFile.Node().(*ast.File)
|
file := curFile.Node().(*ast.File)
|
||||||
for curCall := range curFile.Preorder((*ast.CallExpr)(nil)) {
|
for curCall := range curFile.Preorder((*ast.CallExpr)(nil)) {
|
||||||
call := curCall.Node().(*ast.CallExpr)
|
call := curCall.Node().(*ast.CallExpr)
|
||||||
|
|
|
||||||
13
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/sortslice.go
generated
vendored
13
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/sortslice.go
generated
vendored
|
|
@ -11,20 +11,19 @@ import (
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
// (Not to be confused with go/analysis/passes/sortslice.)
|
// (Not to be confused with go/analysis/passes/sortslice.)
|
||||||
var SlicesSortAnalyzer = &analysis.Analyzer{
|
var SlicesSortAnalyzer = &analysis.Analyzer{
|
||||||
Name: "slicessort",
|
Name: "slicessort",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "slicessort"),
|
Doc: analyzerutil.MustExtractDoc(doc, "slicessort"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -52,8 +51,6 @@ var SlicesSortAnalyzer = &analysis.Analyzer{
|
||||||
// - sort.Sort(x) where x has a named slice type whose Less method is the natural order.
|
// - sort.Sort(x) where x has a named slice type whose Less method is the natural order.
|
||||||
// -> sort.Slice(x)
|
// -> sort.Slice(x)
|
||||||
func slicessort(pass *analysis.Pass) (any, error) {
|
func slicessort(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
// Skip the analyzer in packages where its
|
// Skip the analyzer in packages where its
|
||||||
// fixes would create an import cycle.
|
// fixes would create an import cycle.
|
||||||
if within(pass, "slices", "sort", "runtime") {
|
if within(pass, "slices", "sort", "runtime") {
|
||||||
|
|
@ -87,7 +84,7 @@ func slicessort(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
file := astutil.EnclosingFile(curCall)
|
file := astutil.EnclosingFile(curCall)
|
||||||
if isIndex(compare.X, i) && isIndex(compare.Y, j) &&
|
if isIndex(compare.X, i) && isIndex(compare.Y, j) &&
|
||||||
fileUses(info, file, "go1.21") {
|
analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_21) {
|
||||||
// Have: sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
|
// Have: sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
|
||||||
|
|
||||||
prefix, importEdits := refactor.AddImport(
|
prefix, importEdits := refactor.AddImport(
|
||||||
|
|
|
||||||
67
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/stditerators.go
generated
vendored
67
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/stditerators.go
generated
vendored
|
|
@ -14,9 +14,8 @@ import (
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/goplsexport"
|
"golang.org/x/tools/internal/goplsexport"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
|
|
@ -26,9 +25,8 @@ import (
|
||||||
|
|
||||||
var stditeratorsAnalyzer = &analysis.Analyzer{
|
var stditeratorsAnalyzer = &analysis.Analyzer{
|
||||||
Name: "stditerators",
|
Name: "stditerators",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "stditerators"),
|
Doc: analyzerutil.MustExtractDoc(doc, "stditerators"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
Run: stditerators,
|
Run: stditerators,
|
||||||
|
|
@ -89,8 +87,6 @@ var stditeratorsTable = [...]struct {
|
||||||
// iterator for that reason? We don't want to go fix to
|
// iterator for that reason? We don't want to go fix to
|
||||||
// undo optimizations. Do we need a suppression mechanism?
|
// undo optimizations. Do we need a suppression mechanism?
|
||||||
func stditerators(pass *analysis.Pass) (any, error) {
|
func stditerators(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
info = pass.TypesInfo
|
info = pass.TypesInfo
|
||||||
|
|
@ -116,6 +112,10 @@ func stditerators(pass *analysis.Pass) (any, error) {
|
||||||
//
|
//
|
||||||
// for ... { e := x.At(i); use(e) }
|
// for ... { e := x.At(i); use(e) }
|
||||||
//
|
//
|
||||||
|
// or
|
||||||
|
//
|
||||||
|
// for ... { if e := x.At(i); cond { use(e) } }
|
||||||
|
//
|
||||||
// then chooseName prefers the name e and additionally
|
// then chooseName prefers the name e and additionally
|
||||||
// returns the var's symbol. We'll transform this to:
|
// returns the var's symbol. We'll transform this to:
|
||||||
//
|
//
|
||||||
|
|
@ -124,10 +124,11 @@ func stditerators(pass *analysis.Pass) (any, error) {
|
||||||
// which leaves a redundant assignment that a
|
// which leaves a redundant assignment that a
|
||||||
// subsequent 'forvar' pass will eliminate.
|
// subsequent 'forvar' pass will eliminate.
|
||||||
chooseName := func(curBody inspector.Cursor, x ast.Expr, i *types.Var) (string, *types.Var) {
|
chooseName := func(curBody inspector.Cursor, x ast.Expr, i *types.Var) (string, *types.Var) {
|
||||||
// Is body { elem := x.At(i); ... } ?
|
|
||||||
body := curBody.Node().(*ast.BlockStmt)
|
// isVarAssign reports whether stmt has the form v := x.At(i)
|
||||||
if len(body.List) > 0 {
|
// and returns the variable if so.
|
||||||
if assign, ok := body.List[0].(*ast.AssignStmt); ok &&
|
isVarAssign := func(stmt ast.Stmt) *types.Var {
|
||||||
|
if assign, ok := stmt.(*ast.AssignStmt); ok &&
|
||||||
assign.Tok == token.DEFINE &&
|
assign.Tok == token.DEFINE &&
|
||||||
len(assign.Lhs) == 1 &&
|
len(assign.Lhs) == 1 &&
|
||||||
len(assign.Rhs) == 1 &&
|
len(assign.Rhs) == 1 &&
|
||||||
|
|
@ -138,15 +139,47 @@ func stditerators(pass *analysis.Pass) (any, error) {
|
||||||
astutil.EqualSyntax(ast.Unparen(call.Fun).(*ast.SelectorExpr).X, x) &&
|
astutil.EqualSyntax(ast.Unparen(call.Fun).(*ast.SelectorExpr).X, x) &&
|
||||||
is[*ast.Ident](call.Args[0]) &&
|
is[*ast.Ident](call.Args[0]) &&
|
||||||
info.Uses[call.Args[0].(*ast.Ident)] == i {
|
info.Uses[call.Args[0].(*ast.Ident)] == i {
|
||||||
// Have: { elem := x.At(i); ... }
|
// Have: elem := x.At(i)
|
||||||
id := assign.Lhs[0].(*ast.Ident)
|
id := assign.Lhs[0].(*ast.Ident)
|
||||||
return id.Name, info.Defs[id].(*types.Var)
|
return info.Defs[id].(*types.Var)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
body := curBody.Node().(*ast.BlockStmt)
|
||||||
|
if len(body.List) > 0 {
|
||||||
|
// Is body { elem := x.At(i); ... } ?
|
||||||
|
if v := isVarAssign(body.List[0]); v != nil {
|
||||||
|
return v.Name(), v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or { if elem := x.At(i); cond { ... } } ?
|
||||||
|
if ifstmt, ok := body.List[0].(*ast.IfStmt); ok && ifstmt.Init != nil {
|
||||||
|
if v := isVarAssign(ifstmt.Init); v != nil {
|
||||||
|
return v.Name(), v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loop := curBody.Parent().Node()
|
loop := curBody.Parent().Node()
|
||||||
return refactor.FreshName(info.Scopes[loop], loop.Pos(), row.elemname), nil
|
|
||||||
|
// Choose a fresh name only if
|
||||||
|
// (a) the preferred name is already declared here, and
|
||||||
|
// (b) there are references to it from the loop body.
|
||||||
|
// TODO(adonovan): this pattern also appears in errorsastype,
|
||||||
|
// and is wanted elsewhere; factor.
|
||||||
|
name := row.elemname
|
||||||
|
if v := lookup(info, curBody, name); v != nil {
|
||||||
|
// is it free in body?
|
||||||
|
for curUse := range index.Uses(v) {
|
||||||
|
if curBody.Contains(curUse) {
|
||||||
|
name = refactor.FreshName(info.Scopes[loop], loop.Pos(), name)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process each call of x.Len().
|
// Process each call of x.Len().
|
||||||
|
|
@ -191,7 +224,7 @@ func stditerators(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
// Have: for i := 0; i < x.Len(); i++ { ... }.
|
// Have: for i := 0; i < x.Len(); i++ { ... }.
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
rng = analysisinternal.Range(loop.For, loop.Post.End())
|
rng = astutil.RangeOf(loop.For, loop.Post.End())
|
||||||
indexVar = v
|
indexVar = v
|
||||||
curBody = curFor.ChildAt(edge.ForStmt_Body, -1)
|
curBody = curFor.ChildAt(edge.ForStmt_Body, -1)
|
||||||
elem, elemVar = chooseName(curBody, lenSel.X, indexVar)
|
elem, elemVar = chooseName(curBody, lenSel.X, indexVar)
|
||||||
|
|
@ -234,7 +267,7 @@ func stditerators(pass *analysis.Pass) (any, error) {
|
||||||
// Have: for i := range x.Len() { ... }
|
// Have: for i := range x.Len() { ... }
|
||||||
// ~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~
|
||||||
|
|
||||||
rng = analysisinternal.Range(loop.Range, loop.X.End())
|
rng = astutil.RangeOf(loop.Range, loop.X.End())
|
||||||
indexVar = info.Defs[id].(*types.Var)
|
indexVar = info.Defs[id].(*types.Var)
|
||||||
curBody = curRange.ChildAt(edge.RangeStmt_Body, -1)
|
curBody = curRange.ChildAt(edge.RangeStmt_Body, -1)
|
||||||
elem, elemVar = chooseName(curBody, lenSel.X, indexVar)
|
elem, elemVar = chooseName(curBody, lenSel.X, indexVar)
|
||||||
|
|
@ -313,7 +346,7 @@ func stditerators(pass *analysis.Pass) (any, error) {
|
||||||
// may be somewhat expensive.)
|
// may be somewhat expensive.)
|
||||||
if v, ok := methodGoVersion(row.pkgpath, row.typename, row.itermethod); !ok {
|
if v, ok := methodGoVersion(row.pkgpath, row.typename, row.itermethod); !ok {
|
||||||
panic("no version found")
|
panic("no version found")
|
||||||
} else if file := astutil.EnclosingFile(curLenCall); !fileUses(info, file, v.String()) {
|
} else if !analyzerutil.FileUsesGoVersion(pass, astutil.EnclosingFile(curLenCall), v.String()) {
|
||||||
continue nextCall
|
continue nextCall
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsbuilder.go
generated
vendored
10
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsbuilder.go
generated
vendored
|
|
@ -15,9 +15,8 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
|
|
@ -26,9 +25,8 @@ import (
|
||||||
|
|
||||||
var StringsBuilderAnalyzer = &analysis.Analyzer{
|
var StringsBuilderAnalyzer = &analysis.Analyzer{
|
||||||
Name: "stringsbuilder",
|
Name: "stringsbuilder",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "stringsbuilder"),
|
Doc: analyzerutil.MustExtractDoc(doc, "stringsbuilder"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -38,8 +36,6 @@ var StringsBuilderAnalyzer = &analysis.Analyzer{
|
||||||
|
|
||||||
// stringsbuilder replaces string += string in a loop by strings.Builder.
|
// stringsbuilder replaces string += string in a loop by strings.Builder.
|
||||||
func stringsbuilder(pass *analysis.Pass) (any, error) {
|
func stringsbuilder(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
// Skip the analyzer in packages where its
|
// Skip the analyzer in packages where its
|
||||||
// fixes would create an import cycle.
|
// fixes would create an import cycle.
|
||||||
if within(pass, "strings", "runtime") {
|
if within(pass, "strings", "runtime") {
|
||||||
|
|
|
||||||
580
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscut.go
generated
vendored
Normal file
580
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscut.go
generated
vendored
Normal file
|
|
@ -0,0 +1,580 @@
|
||||||
|
// Copyright 2025 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 modernize
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/constant"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"iter"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
|
"golang.org/x/tools/go/ast/edge"
|
||||||
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
|
"golang.org/x/tools/internal/astutil"
|
||||||
|
"golang.org/x/tools/internal/goplsexport"
|
||||||
|
"golang.org/x/tools/internal/refactor"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
|
)
|
||||||
|
|
||||||
|
var stringscutAnalyzer = &analysis.Analyzer{
|
||||||
|
Name: "stringscut",
|
||||||
|
Doc: analyzerutil.MustExtractDoc(doc, "stringscut"),
|
||||||
|
Requires: []*analysis.Analyzer{
|
||||||
|
inspect.Analyzer,
|
||||||
|
typeindexanalyzer.Analyzer,
|
||||||
|
},
|
||||||
|
Run: stringscut,
|
||||||
|
URL: "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/modernize#stringscut",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Export to gopls until this is a published modernizer.
|
||||||
|
goplsexport.StringsCutModernizer = stringscutAnalyzer
|
||||||
|
}
|
||||||
|
|
||||||
|
// stringscut offers a fix to replace an occurrence of strings.Index{,Byte} with
|
||||||
|
// strings.{Cut,Contains}, and similar fixes for functions in the bytes package.
|
||||||
|
// Consider some candidate for replacement i := strings.Index(s, substr).
|
||||||
|
// The following must hold for a replacement to occur:
|
||||||
|
//
|
||||||
|
// 1. All instances of i and s must be in one of these forms.
|
||||||
|
// Binary expressions:
|
||||||
|
// (a): establishing that i < 0: e.g.: i < 0, 0 > i, i == -1, -1 == i
|
||||||
|
// (b): establishing that i > -1: e.g.: i >= 0, 0 <= i, i == 0, 0 == i
|
||||||
|
//
|
||||||
|
// Slice expressions:
|
||||||
|
// a: s[:i], s[0:i]
|
||||||
|
// b: s[i+len(substr):], s[len(substr) + i:], s[i + const], s[k + i] (where k = len(substr))
|
||||||
|
//
|
||||||
|
// 2. There can be no uses of s, substr, or i where they are
|
||||||
|
// potentially modified (i.e. in assignments, or function calls with unknown side
|
||||||
|
// effects).
|
||||||
|
//
|
||||||
|
// Then, the replacement involves the following substitutions:
|
||||||
|
//
|
||||||
|
// 1. Replace "i := strings.Index(s, substr)" with "before, after, ok := strings.Cut(s, substr)"
|
||||||
|
//
|
||||||
|
// 2. Replace instances of binary expressions (a) with !ok and binary expressions (b) with ok.
|
||||||
|
//
|
||||||
|
// 3. Replace slice expressions (a) with "before" and slice expressions (b) with after.
|
||||||
|
//
|
||||||
|
// 4. The assignments to before, after, and ok may use the blank identifier "_" if they are unused.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// i := strings.Index(s, substr)
|
||||||
|
// if i >= 0 {
|
||||||
|
// use(s[:i], s[i+len(substr):])
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Would become:
|
||||||
|
//
|
||||||
|
// before, after, ok := strings.Cut(s, substr)
|
||||||
|
// if ok {
|
||||||
|
// use(before, after)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// If the condition involving `i` establishes that i > -1, then we replace it with
|
||||||
|
// `if ok“. Variants listed above include i >= 0, i > 0, and i == 0.
|
||||||
|
// If the condition is negated (e.g. establishes `i < 0`), we use `if !ok` instead.
|
||||||
|
// If the slices of `s` match `s[:i]` or `s[i+len(substr):]` or their variants listed above,
|
||||||
|
// then we replace them with before and after.
|
||||||
|
//
|
||||||
|
// When the index `i` is used only to check for the presence of the substring or byte slice,
|
||||||
|
// the suggested fix uses Contains() instead of Cut.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// i := strings.Index(s, substr)
|
||||||
|
// if i >= 0 {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Would become:
|
||||||
|
//
|
||||||
|
// found := strings.Contains(s, substr)
|
||||||
|
// if found {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
func stringscut(pass *analysis.Pass) (any, error) {
|
||||||
|
var (
|
||||||
|
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
|
info = pass.TypesInfo
|
||||||
|
|
||||||
|
stringsIndex = index.Object("strings", "Index")
|
||||||
|
stringsIndexByte = index.Object("strings", "IndexByte")
|
||||||
|
bytesIndex = index.Object("bytes", "Index")
|
||||||
|
bytesIndexByte = index.Object("bytes", "IndexByte")
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, obj := range []types.Object{
|
||||||
|
stringsIndex,
|
||||||
|
stringsIndexByte,
|
||||||
|
bytesIndex,
|
||||||
|
bytesIndexByte,
|
||||||
|
} {
|
||||||
|
// (obj may be nil)
|
||||||
|
nextcall:
|
||||||
|
for curCall := range index.Calls(obj) {
|
||||||
|
// Check file version.
|
||||||
|
if !analyzerutil.FileUsesGoVersion(pass, astutil.EnclosingFile(curCall), versions.Go1_18) {
|
||||||
|
continue // strings.Index not available in this file
|
||||||
|
}
|
||||||
|
indexCall := curCall.Node().(*ast.CallExpr) // the call to strings.Index, etc.
|
||||||
|
obj := typeutil.Callee(info, indexCall)
|
||||||
|
if obj == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var iIdent *ast.Ident // defining identifier of i var
|
||||||
|
switch ek, idx := curCall.ParentEdge(); ek {
|
||||||
|
case edge.ValueSpec_Values:
|
||||||
|
// Have: var i = strings.Index(...)
|
||||||
|
curName := curCall.Parent().ChildAt(edge.ValueSpec_Names, idx)
|
||||||
|
iIdent = curName.Node().(*ast.Ident)
|
||||||
|
case edge.AssignStmt_Rhs:
|
||||||
|
// Have: i := strings.Index(...)
|
||||||
|
// (Must be i's definition.)
|
||||||
|
curLhs := curCall.Parent().ChildAt(edge.AssignStmt_Lhs, idx)
|
||||||
|
iIdent, _ = curLhs.Node().(*ast.Ident) // may be nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if iIdent == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Inv: iIdent is i's definition. The following would be skipped: 'var i int; i = strings.Index(...)'
|
||||||
|
// Get uses of i.
|
||||||
|
iObj := info.ObjectOf(iIdent)
|
||||||
|
if iObj == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
s = indexCall.Args[0]
|
||||||
|
substr = indexCall.Args[1]
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check that there are no statements that alter the value of s
|
||||||
|
// or substr after the call to Index().
|
||||||
|
if !indexArgValid(info, index, s, indexCall.Pos()) ||
|
||||||
|
!indexArgValid(info, index, substr, indexCall.Pos()) {
|
||||||
|
continue nextcall
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, examine all uses of i. If the only uses are of the
|
||||||
|
// forms mentioned above (e.g. i < 0, i >= 0, s[:i] and s[i +
|
||||||
|
// len(substr)]), then we can replace the call to Index()
|
||||||
|
// with a call to Cut() and use the returned ok, before,
|
||||||
|
// and after variables accordingly.
|
||||||
|
lessZero, greaterNegOne, beforeSlice, afterSlice := checkIdxUses(pass.TypesInfo, index.Uses(iObj), s, substr)
|
||||||
|
|
||||||
|
// Either there are no uses of before, after, or ok, or some use
|
||||||
|
// of i does not match our criteria - don't suggest a fix.
|
||||||
|
if lessZero == nil && greaterNegOne == nil && beforeSlice == nil && afterSlice == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the only uses are ok and !ok, don't suggest a Cut() fix - these should be using Contains()
|
||||||
|
isContains := (len(lessZero) > 0 || len(greaterNegOne) > 0) && len(beforeSlice) == 0 && len(afterSlice) == 0
|
||||||
|
|
||||||
|
scope := iObj.Parent()
|
||||||
|
var (
|
||||||
|
// TODO(adonovan): avoid FreshName when not needed; see errorsastype.
|
||||||
|
okVarName = refactor.FreshName(scope, iIdent.Pos(), "ok")
|
||||||
|
beforeVarName = refactor.FreshName(scope, iIdent.Pos(), "before")
|
||||||
|
afterVarName = refactor.FreshName(scope, iIdent.Pos(), "after")
|
||||||
|
foundVarName = refactor.FreshName(scope, iIdent.Pos(), "found") // for Contains()
|
||||||
|
)
|
||||||
|
|
||||||
|
// If there will be no uses of ok, before, or after, use the
|
||||||
|
// blank identifier instead.
|
||||||
|
if len(lessZero) == 0 && len(greaterNegOne) == 0 {
|
||||||
|
okVarName = "_"
|
||||||
|
}
|
||||||
|
if len(beforeSlice) == 0 {
|
||||||
|
beforeVarName = "_"
|
||||||
|
}
|
||||||
|
if len(afterSlice) == 0 {
|
||||||
|
afterVarName = "_"
|
||||||
|
}
|
||||||
|
|
||||||
|
var edits []analysis.TextEdit
|
||||||
|
replace := func(exprs []ast.Expr, new string) {
|
||||||
|
for _, expr := range exprs {
|
||||||
|
edits = append(edits, analysis.TextEdit{
|
||||||
|
Pos: expr.Pos(),
|
||||||
|
End: expr.End(),
|
||||||
|
NewText: []byte(new),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get the ident for the call to strings.Index, which could just be
|
||||||
|
// "Index" if the strings package is dot imported.
|
||||||
|
indexCallId := typesinternal.UsedIdent(info, indexCall.Fun)
|
||||||
|
replacedFunc := "Cut"
|
||||||
|
if isContains {
|
||||||
|
replacedFunc = "Contains"
|
||||||
|
replace(lessZero, "!"+foundVarName) // idx < 0 -> !found
|
||||||
|
replace(greaterNegOne, foundVarName) // idx > -1 -> found
|
||||||
|
|
||||||
|
// Replace the assignment with found, and replace the call to
|
||||||
|
// Index or IndexByte with a call to Contains.
|
||||||
|
// i := strings.Index (...)
|
||||||
|
// ----- --------
|
||||||
|
// found := strings.Contains(...)
|
||||||
|
edits = append(edits, analysis.TextEdit{
|
||||||
|
Pos: iIdent.Pos(),
|
||||||
|
End: iIdent.End(),
|
||||||
|
NewText: []byte(foundVarName),
|
||||||
|
}, analysis.TextEdit{
|
||||||
|
Pos: indexCallId.Pos(),
|
||||||
|
End: indexCallId.End(),
|
||||||
|
NewText: []byte("Contains"),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
replace(lessZero, "!"+okVarName) // idx < 0 -> !ok
|
||||||
|
replace(greaterNegOne, okVarName) // idx > -1 -> ok
|
||||||
|
replace(beforeSlice, beforeVarName) // s[:idx] -> before
|
||||||
|
replace(afterSlice, afterVarName) // s[idx+k:] -> after
|
||||||
|
|
||||||
|
// Replace the assignment with before, after, ok, and replace
|
||||||
|
// the call to Index or IndexByte with a call to Cut.
|
||||||
|
// i := strings.Index(...)
|
||||||
|
// ----------------- -----
|
||||||
|
// before, after, ok := strings.Cut (...)
|
||||||
|
edits = append(edits, analysis.TextEdit{
|
||||||
|
Pos: iIdent.Pos(),
|
||||||
|
End: iIdent.End(),
|
||||||
|
NewText: fmt.Appendf(nil, "%s, %s, %s", beforeVarName, afterVarName, okVarName),
|
||||||
|
}, analysis.TextEdit{
|
||||||
|
Pos: indexCallId.Pos(),
|
||||||
|
End: indexCallId.End(),
|
||||||
|
NewText: []byte("Cut"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calls to IndexByte have a byte as their second arg, which
|
||||||
|
// must be converted to a string or []byte to be a valid arg for Cut/Contains.
|
||||||
|
if obj.Name() == "IndexByte" {
|
||||||
|
switch obj.Pkg().Name() {
|
||||||
|
case "strings":
|
||||||
|
searchByteVal := info.Types[substr].Value
|
||||||
|
if searchByteVal == nil {
|
||||||
|
// substr is a variable, e.g. substr := byte('b')
|
||||||
|
// use string(substr)
|
||||||
|
edits = append(edits, []analysis.TextEdit{
|
||||||
|
{
|
||||||
|
Pos: substr.Pos(),
|
||||||
|
NewText: []byte("string("),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Pos: substr.End(),
|
||||||
|
NewText: []byte(")"),
|
||||||
|
},
|
||||||
|
}...)
|
||||||
|
} else {
|
||||||
|
// substr is a byte constant
|
||||||
|
val, _ := constant.Int64Val(searchByteVal) // inv: must be a valid byte
|
||||||
|
// strings.Cut/Contains requires a string, so convert byte literal to string literal; e.g. 'a' -> "a", 55 -> "7"
|
||||||
|
edits = append(edits, analysis.TextEdit{
|
||||||
|
Pos: substr.Pos(),
|
||||||
|
End: substr.End(),
|
||||||
|
NewText: strconv.AppendQuote(nil, string(byte(val))),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
case "bytes":
|
||||||
|
// bytes.Cut/Contains requires a []byte, so wrap substr in a []byte{}
|
||||||
|
edits = append(edits, []analysis.TextEdit{
|
||||||
|
{
|
||||||
|
Pos: substr.Pos(),
|
||||||
|
NewText: []byte("[]byte{"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Pos: substr.End(),
|
||||||
|
NewText: []byte("}"),
|
||||||
|
},
|
||||||
|
}...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pass.Report(analysis.Diagnostic{
|
||||||
|
Pos: indexCall.Fun.Pos(),
|
||||||
|
End: indexCall.Fun.End(),
|
||||||
|
Message: fmt.Sprintf("%s.%s can be simplified using %s.%s",
|
||||||
|
obj.Pkg().Name(), obj.Name(), obj.Pkg().Name(), replacedFunc),
|
||||||
|
Category: "stringscut",
|
||||||
|
SuggestedFixes: []analysis.SuggestedFix{{
|
||||||
|
Message: fmt.Sprintf("Simplify %s.%s call using %s.%s", obj.Pkg().Name(), obj.Name(), obj.Pkg().Name(), replacedFunc),
|
||||||
|
TextEdits: edits,
|
||||||
|
}},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// indexArgValid reports whether expr is a valid strings.Index(_, _) arg
|
||||||
|
// for the transformation. An arg is valid iff it is:
|
||||||
|
// - constant;
|
||||||
|
// - a local variable with no modifying uses after the Index() call; or
|
||||||
|
// - []byte(x) where x is also valid by this definition.
|
||||||
|
// All other expressions are assumed not referentially transparent,
|
||||||
|
// so we cannot be sure that all uses are safe to replace.
|
||||||
|
func indexArgValid(info *types.Info, index *typeindex.Index, expr ast.Expr, afterPos token.Pos) bool {
|
||||||
|
tv := info.Types[expr]
|
||||||
|
if tv.Value != nil {
|
||||||
|
return true // constant
|
||||||
|
}
|
||||||
|
switch expr := expr.(type) {
|
||||||
|
case *ast.CallExpr:
|
||||||
|
return types.Identical(tv.Type, byteSliceType) &&
|
||||||
|
indexArgValid(info, index, expr.Args[0], afterPos) // check s in []byte(s)
|
||||||
|
case *ast.Ident:
|
||||||
|
sObj := info.Uses[expr]
|
||||||
|
sUses := index.Uses(sObj)
|
||||||
|
return !hasModifyingUses(info, sUses, afterPos)
|
||||||
|
default:
|
||||||
|
// For now, skip instances where s or substr are not
|
||||||
|
// identifers, basic lits, or call expressions of the form
|
||||||
|
// []byte(s).
|
||||||
|
// TODO(mkalil): Handle s and substr being expressions like ptr.field[i].
|
||||||
|
// From adonovan: We'd need to analyze s and substr to see
|
||||||
|
// whether they are referentially transparent, and if not,
|
||||||
|
// analyze all code between declaration and use and see if
|
||||||
|
// there are statements or expressions with potential side
|
||||||
|
// effects.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkIdxUses inspects the uses of i to make sure they match certain criteria that
|
||||||
|
// allows us to suggest a modernization. If all uses of i, s and substr match
|
||||||
|
// one of the following four valid formats, it returns a list of occurrences for
|
||||||
|
// each format. If any of the uses do not match one of the formats, return nil
|
||||||
|
// for all values, since we should not offer a replacement.
|
||||||
|
// 1. lessZero - a condition involving i establishing that i is negative (e.g. i < 0, 0 > i, i == -1, -1 == i)
|
||||||
|
// 2. greaterNegOne - a condition involving i establishing that i is non-negative (e.g. i >= 0, 0 <= i, i == 0, 0 == i)
|
||||||
|
// 3. beforeSlice - a slice of `s` that matches either s[:i], s[0:i]
|
||||||
|
// 4. afterSlice - a slice of `s` that matches one of: s[i+len(substr):], s[len(substr) + i:], s[i + const], s[k + i] (where k = len(substr))
|
||||||
|
func checkIdxUses(info *types.Info, uses iter.Seq[inspector.Cursor], s, substr ast.Expr) (lessZero, greaterNegOne, beforeSlice, afterSlice []ast.Expr) {
|
||||||
|
use := func(cur inspector.Cursor) bool {
|
||||||
|
ek, _ := cur.ParentEdge()
|
||||||
|
n := cur.Parent().Node()
|
||||||
|
switch ek {
|
||||||
|
case edge.BinaryExpr_X, edge.BinaryExpr_Y:
|
||||||
|
check := n.(*ast.BinaryExpr)
|
||||||
|
switch checkIdxComparison(info, check) {
|
||||||
|
case -1:
|
||||||
|
lessZero = append(lessZero, check)
|
||||||
|
return true
|
||||||
|
case 1:
|
||||||
|
greaterNegOne = append(greaterNegOne, check)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// Check does not establish that i < 0 or i > -1.
|
||||||
|
// Might be part of an outer slice expression like s[i + k]
|
||||||
|
// which requires a different check.
|
||||||
|
// Check that the thing being sliced is s and that the slice
|
||||||
|
// doesn't have a max index.
|
||||||
|
if slice, ok := cur.Parent().Parent().Node().(*ast.SliceExpr); ok &&
|
||||||
|
sameObject(info, s, slice.X) &&
|
||||||
|
slice.Max == nil {
|
||||||
|
if isBeforeSlice(info, ek, slice) {
|
||||||
|
beforeSlice = append(beforeSlice, slice)
|
||||||
|
return true
|
||||||
|
} else if isAfterSlice(info, ek, slice, substr) {
|
||||||
|
afterSlice = append(afterSlice, slice)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case edge.SliceExpr_Low, edge.SliceExpr_High:
|
||||||
|
slice := n.(*ast.SliceExpr)
|
||||||
|
// Check that the thing being sliced is s and that the slice doesn't
|
||||||
|
// have a max index.
|
||||||
|
if sameObject(info, s, slice.X) && slice.Max == nil {
|
||||||
|
if isBeforeSlice(info, ek, slice) {
|
||||||
|
beforeSlice = append(beforeSlice, slice)
|
||||||
|
return true
|
||||||
|
} else if isAfterSlice(info, ek, slice, substr) {
|
||||||
|
afterSlice = append(afterSlice, slice)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for curIdent := range uses {
|
||||||
|
if !use(curIdent) {
|
||||||
|
return nil, nil, nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lessZero, greaterNegOne, beforeSlice, afterSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasModifyingUses reports whether any of the uses involve potential
|
||||||
|
// modifications. Uses involving assignments before the "afterPos" won't be
|
||||||
|
// considered.
|
||||||
|
func hasModifyingUses(info *types.Info, uses iter.Seq[inspector.Cursor], afterPos token.Pos) bool {
|
||||||
|
for curUse := range uses {
|
||||||
|
ek, _ := curUse.ParentEdge()
|
||||||
|
if ek == edge.AssignStmt_Lhs {
|
||||||
|
if curUse.Node().Pos() <= afterPos {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
assign := curUse.Parent().Node().(*ast.AssignStmt)
|
||||||
|
if sameObject(info, assign.Lhs[0], curUse.Node().(*ast.Ident)) {
|
||||||
|
// Modifying use because we are reassigning the value of the object.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else if ek == edge.UnaryExpr_X &&
|
||||||
|
curUse.Parent().Node().(*ast.UnaryExpr).Op == token.AND {
|
||||||
|
// Modifying use because we might be passing the object by reference (an explicit &).
|
||||||
|
// We can ignore the case where we have a method call on the expression (which
|
||||||
|
// has an implicit &) because we know the type of s and substr are strings
|
||||||
|
// which cannot have methods on them.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkIdxComparison reports whether the check establishes that i is negative
|
||||||
|
// or non-negative. It returns -1 in the first case, 1 in the second, and 0 if
|
||||||
|
// we can confirm neither condition. We assume that a check passed to
|
||||||
|
// checkIdxComparison has i as one of its operands.
|
||||||
|
func checkIdxComparison(info *types.Info, check *ast.BinaryExpr) int {
|
||||||
|
// Check establishes that i is negative.
|
||||||
|
// e.g.: i < 0, 0 > i, i == -1, -1 == i
|
||||||
|
if check.Op == token.LSS && (isNegativeConst(info, check.Y) || isZeroIntConst(info, check.Y)) || //i < (0 or neg)
|
||||||
|
check.Op == token.GTR && (isNegativeConst(info, check.X) || isZeroIntConst(info, check.X)) || // (0 or neg) > i
|
||||||
|
check.Op == token.LEQ && (isNegativeConst(info, check.Y)) || //i <= (neg)
|
||||||
|
check.Op == token.GEQ && (isNegativeConst(info, check.X)) || // (neg) >= i
|
||||||
|
check.Op == token.EQL &&
|
||||||
|
(isNegativeConst(info, check.X) || isNegativeConst(info, check.Y)) { // i == neg; neg == i
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
// Check establishes that i is non-negative.
|
||||||
|
// e.g.: i >= 0, 0 <= i, i == 0, 0 == i
|
||||||
|
if check.Op == token.GTR && (isNonNegativeConst(info, check.Y) || isIntLiteral(info, check.Y, -1)) || // i > (non-neg or -1)
|
||||||
|
check.Op == token.LSS && (isNonNegativeConst(info, check.X) || isIntLiteral(info, check.X, -1)) || // (non-neg or -1) < i
|
||||||
|
check.Op == token.GEQ && isNonNegativeConst(info, check.Y) || // i >= (non-neg)
|
||||||
|
check.Op == token.LEQ && isNonNegativeConst(info, check.X) || // (non-neg) <= i
|
||||||
|
check.Op == token.EQL &&
|
||||||
|
(isNonNegativeConst(info, check.X) || isNonNegativeConst(info, check.Y)) { // i == non-neg; non-neg == i
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNegativeConst returns true if the expr is a const int with value < zero.
|
||||||
|
func isNegativeConst(info *types.Info, expr ast.Expr) bool {
|
||||||
|
if tv, ok := info.Types[expr]; ok && tv.Value != nil && tv.Value.Kind() == constant.Int {
|
||||||
|
if v, ok := constant.Int64Val(tv.Value); ok {
|
||||||
|
return v < 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNoneNegativeConst returns true if the expr is a const int with value >= zero.
|
||||||
|
func isNonNegativeConst(info *types.Info, expr ast.Expr) bool {
|
||||||
|
if tv, ok := info.Types[expr]; ok && tv.Value != nil && tv.Value.Kind() == constant.Int {
|
||||||
|
if v, ok := constant.Int64Val(tv.Value); ok {
|
||||||
|
return v >= 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// isBeforeSlice reports whether the SliceExpr is of the form s[:i] or s[0:i].
|
||||||
|
func isBeforeSlice(info *types.Info, ek edge.Kind, slice *ast.SliceExpr) bool {
|
||||||
|
return ek == edge.SliceExpr_High && (slice.Low == nil || isZeroIntConst(info, slice.Low))
|
||||||
|
}
|
||||||
|
|
||||||
|
// isAfterSlice reports whether the SliceExpr is of the form s[i+len(substr):],
|
||||||
|
// or s[i + k:] where k is a const is equal to len(substr).
|
||||||
|
func isAfterSlice(info *types.Info, ek edge.Kind, slice *ast.SliceExpr, substr ast.Expr) bool {
|
||||||
|
lowExpr, ok := slice.Low.(*ast.BinaryExpr)
|
||||||
|
if !ok || slice.High != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Returns true if the expression is a call to len(substr).
|
||||||
|
isLenCall := func(expr ast.Expr) bool {
|
||||||
|
call, ok := expr.(*ast.CallExpr)
|
||||||
|
if !ok || len(call.Args) != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return sameObject(info, substr, call.Args[0]) && typeutil.Callee(info, call) == builtinLen
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle len([]byte(substr))
|
||||||
|
if is[*ast.CallExpr](substr) {
|
||||||
|
call := substr.(*ast.CallExpr)
|
||||||
|
tv := info.Types[call.Fun]
|
||||||
|
if tv.IsType() && types.Identical(tv.Type, byteSliceType) {
|
||||||
|
// Only one arg in []byte conversion.
|
||||||
|
substr = call.Args[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
substrLen := -1
|
||||||
|
substrVal := info.Types[substr].Value
|
||||||
|
if substrVal != nil {
|
||||||
|
switch substrVal.Kind() {
|
||||||
|
case constant.String:
|
||||||
|
substrLen = len(constant.StringVal(substrVal))
|
||||||
|
case constant.Int:
|
||||||
|
// constant.Value is a byte literal, e.g. bytes.IndexByte(_, 'a')
|
||||||
|
// or a numeric byte literal, e.g. bytes.IndexByte(_, 65)
|
||||||
|
substrLen = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ek {
|
||||||
|
case edge.BinaryExpr_X:
|
||||||
|
kVal := info.Types[lowExpr.Y].Value
|
||||||
|
if kVal == nil {
|
||||||
|
// i + len(substr)
|
||||||
|
return lowExpr.Op == token.ADD && isLenCall(lowExpr.Y)
|
||||||
|
} else {
|
||||||
|
// i + k
|
||||||
|
kInt, ok := constant.Int64Val(kVal)
|
||||||
|
return ok && substrLen == int(kInt)
|
||||||
|
}
|
||||||
|
case edge.BinaryExpr_Y:
|
||||||
|
kVal := info.Types[lowExpr.X].Value
|
||||||
|
if kVal == nil {
|
||||||
|
// len(substr) + i
|
||||||
|
return lowExpr.Op == token.ADD && isLenCall(lowExpr.X)
|
||||||
|
} else {
|
||||||
|
// k + i
|
||||||
|
kInt, ok := constant.Int64Val(kVal)
|
||||||
|
return ok && substrLen == int(kInt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// sameObject reports whether we know that the expressions resolve to the same object.
|
||||||
|
func sameObject(info *types.Info, expr1, expr2 ast.Expr) bool {
|
||||||
|
if ident1, ok := expr1.(*ast.Ident); ok {
|
||||||
|
if ident2, ok := expr2.(*ast.Ident); ok {
|
||||||
|
uses1, ok1 := info.Uses[ident1]
|
||||||
|
uses2, ok2 := info.Uses[ident2]
|
||||||
|
return ok1 && ok2 && uses1 == uses2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
20
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscutprefix.go
generated
vendored
20
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringscutprefix.go
generated
vendored
|
|
@ -12,22 +12,20 @@ import (
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var StringsCutPrefixAnalyzer = &analysis.Analyzer{
|
var StringsCutPrefixAnalyzer = &analysis.Analyzer{
|
||||||
Name: "stringscutprefix",
|
Name: "stringscutprefix",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "stringscutprefix"),
|
Doc: analyzerutil.MustExtractDoc(doc, "stringscutprefix"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -56,12 +54,9 @@ var StringsCutPrefixAnalyzer = &analysis.Analyzer{
|
||||||
// Variants:
|
// Variants:
|
||||||
// - bytes.HasPrefix/HasSuffix usage as pattern 1.
|
// - bytes.HasPrefix/HasSuffix usage as pattern 1.
|
||||||
func stringscutprefix(pass *analysis.Pass) (any, error) {
|
func stringscutprefix(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
inspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
info = pass.TypesInfo
|
||||||
info = pass.TypesInfo
|
|
||||||
|
|
||||||
stringsTrimPrefix = index.Object("strings", "TrimPrefix")
|
stringsTrimPrefix = index.Object("strings", "TrimPrefix")
|
||||||
bytesTrimPrefix = index.Object("bytes", "TrimPrefix")
|
bytesTrimPrefix = index.Object("bytes", "TrimPrefix")
|
||||||
|
|
@ -72,7 +67,7 @@ func stringscutprefix(pass *analysis.Pass) (any, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for curFile := range filesUsing(inspect, pass.TypesInfo, "go1.20") {
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_20) {
|
||||||
for curIfStmt := range curFile.Preorder((*ast.IfStmt)(nil)) {
|
for curIfStmt := range curFile.Preorder((*ast.IfStmt)(nil)) {
|
||||||
ifStmt := curIfStmt.Node().(*ast.IfStmt)
|
ifStmt := curIfStmt.Node().(*ast.IfStmt)
|
||||||
|
|
||||||
|
|
@ -206,6 +201,7 @@ func stringscutprefix(pass *analysis.Pass) (any, error) {
|
||||||
|
|
||||||
if astutil.EqualSyntax(lhs, bin.X) && astutil.EqualSyntax(call.Args[0], bin.Y) ||
|
if astutil.EqualSyntax(lhs, bin.X) && astutil.EqualSyntax(call.Args[0], bin.Y) ||
|
||||||
(astutil.EqualSyntax(lhs, bin.Y) && astutil.EqualSyntax(call.Args[0], bin.X)) {
|
(astutil.EqualSyntax(lhs, bin.Y) && astutil.EqualSyntax(call.Args[0], bin.X)) {
|
||||||
|
// TODO(adonovan): avoid FreshName when not needed; see errorsastype.
|
||||||
okVarName := refactor.FreshName(info.Scopes[ifStmt], ifStmt.Pos(), "ok")
|
okVarName := refactor.FreshName(info.Scopes[ifStmt], ifStmt.Pos(), "ok")
|
||||||
// Have one of:
|
// Have one of:
|
||||||
// if rest := TrimPrefix(s, prefix); rest != s { (ditto Suffix)
|
// if rest := TrimPrefix(s, prefix); rest != s { (ditto Suffix)
|
||||||
|
|
|
||||||
19
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsseq.go
generated
vendored
19
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/stringsseq.go
generated
vendored
|
|
@ -13,19 +13,17 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var StringsSeqAnalyzer = &analysis.Analyzer{
|
var StringsSeqAnalyzer = &analysis.Analyzer{
|
||||||
Name: "stringsseq",
|
Name: "stringsseq",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "stringsseq"),
|
Doc: analyzerutil.MustExtractDoc(doc, "stringsseq"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -48,12 +46,9 @@ var StringsSeqAnalyzer = &analysis.Analyzer{
|
||||||
// - bytes.SplitSeq
|
// - bytes.SplitSeq
|
||||||
// - bytes.FieldsSeq
|
// - bytes.FieldsSeq
|
||||||
func stringsseq(pass *analysis.Pass) (any, error) {
|
func stringsseq(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
inspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
info = pass.TypesInfo
|
||||||
info = pass.TypesInfo
|
|
||||||
|
|
||||||
stringsSplit = index.Object("strings", "Split")
|
stringsSplit = index.Object("strings", "Split")
|
||||||
stringsFields = index.Object("strings", "Fields")
|
stringsFields = index.Object("strings", "Fields")
|
||||||
|
|
@ -64,7 +59,7 @@ func stringsseq(pass *analysis.Pass) (any, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for curFile := range filesUsing(inspect, info, "go1.24") {
|
for curFile := range filesUsingGoVersion(pass, versions.Go1_24) {
|
||||||
for curRange := range curFile.Preorder((*ast.RangeStmt)(nil)) {
|
for curRange := range curFile.Preorder((*ast.RangeStmt)(nil)) {
|
||||||
rng := curRange.Node().(*ast.RangeStmt)
|
rng := curRange.Node().(*ast.RangeStmt)
|
||||||
|
|
||||||
|
|
|
||||||
13
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/testingcontext.go
generated
vendored
13
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/testingcontext.go
generated
vendored
|
|
@ -17,19 +17,18 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var TestingContextAnalyzer = &analysis.Analyzer{
|
var TestingContextAnalyzer = &analysis.Analyzer{
|
||||||
Name: "testingcontext",
|
Name: "testingcontext",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "testingcontext"),
|
Doc: analyzerutil.MustExtractDoc(doc, "testingcontext"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -56,8 +55,6 @@ var TestingContextAnalyzer = &analysis.Analyzer{
|
||||||
// - the call is within a test or subtest function
|
// - the call is within a test or subtest function
|
||||||
// - the relevant testing.{T,B,F} is named and not shadowed at the call
|
// - the relevant testing.{T,B,F} is named and not shadowed at the call
|
||||||
func testingContext(pass *analysis.Pass) (any, error) {
|
func testingContext(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
info = pass.TypesInfo
|
info = pass.TypesInfo
|
||||||
|
|
@ -137,7 +134,7 @@ calls:
|
||||||
testObj = isTestFn(info, n)
|
testObj = isTestFn(info, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if testObj != nil && fileUses(info, astutil.EnclosingFile(cur), "go1.24") {
|
if testObj != nil && analyzerutil.FileUsesGoVersion(pass, astutil.EnclosingFile(cur), versions.Go1_24) {
|
||||||
// Have a test function. Check that we can resolve the relevant
|
// Have a test function. Check that we can resolve the relevant
|
||||||
// testing.{T,B,F} at the current position.
|
// testing.{T,B,F} at the current position.
|
||||||
if _, obj := lhs[0].Parent().LookupParent(testObj.Name(), lhs[0].Pos()); obj == testObj {
|
if _, obj := lhs[0].Parent().LookupParent(testObj.Name(), lhs[0].Pos()); obj == testObj {
|
||||||
|
|
|
||||||
13
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/waitgroup.go
generated
vendored
13
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/waitgroup.go
generated
vendored
|
|
@ -14,19 +14,18 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal/generated"
|
typeindexanalyzer "golang.org/x/tools/internal/analysis/typeindex"
|
||||||
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typesinternal/typeindex"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var WaitGroupAnalyzer = &analysis.Analyzer{
|
var WaitGroupAnalyzer = &analysis.Analyzer{
|
||||||
Name: "waitgroup",
|
Name: "waitgroup",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "waitgroup"),
|
Doc: analyzerutil.MustExtractDoc(doc, "waitgroup"),
|
||||||
Requires: []*analysis.Analyzer{
|
Requires: []*analysis.Analyzer{
|
||||||
generated.Analyzer,
|
|
||||||
inspect.Analyzer,
|
inspect.Analyzer,
|
||||||
typeindexanalyzer.Analyzer,
|
typeindexanalyzer.Analyzer,
|
||||||
},
|
},
|
||||||
|
|
@ -61,8 +60,6 @@ var WaitGroupAnalyzer = &analysis.Analyzer{
|
||||||
// other effects, or blocked, or if WaitGroup.Go propagated panics
|
// other effects, or blocked, or if WaitGroup.Go propagated panics
|
||||||
// from child to parent goroutine, the argument would be different.)
|
// from child to parent goroutine, the argument would be different.)
|
||||||
func waitgroup(pass *analysis.Pass) (any, error) {
|
func waitgroup(pass *analysis.Pass) (any, error) {
|
||||||
skipGenerated(pass)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
info = pass.TypesInfo
|
info = pass.TypesInfo
|
||||||
|
|
@ -128,7 +125,7 @@ func waitgroup(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
file := astutil.EnclosingFile(curAddCall)
|
file := astutil.EnclosingFile(curAddCall)
|
||||||
if !fileUses(info, file, "go1.25") {
|
if !analyzerutil.FileUsesGoVersion(pass, file, versions.Go1_25) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tokFile := pass.Fset.File(file.Pos())
|
tokFile := pass.Fset.File(file.Pos())
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc/nilfunc.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/nilfunc/nilfunc.go
generated
vendored
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "nilfunc",
|
Name: "nilfunc",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "nilfunc"),
|
Doc: analyzerutil.MustExtractDoc(doc, "nilfunc"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/nilfunc",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/nilfunc",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
|
||||||
24
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go
generated
vendored
24
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go
generated
vendored
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"golang.org/x/tools/go/ast/edge"
|
"golang.org/x/tools/go/ast/edge"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/fmtstr"
|
"golang.org/x/tools/internal/fmtstr"
|
||||||
"golang.org/x/tools/internal/typeparams"
|
"golang.org/x/tools/internal/typeparams"
|
||||||
|
|
@ -38,7 +38,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "printf",
|
Name: "printf",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "printf"),
|
Doc: analyzerutil.MustExtractDoc(doc, "printf"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/printf",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/printf",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
@ -612,7 +612,7 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C
|
||||||
// breaking existing tests and CI scripts.
|
// breaking existing tests and CI scripts.
|
||||||
if idx == len(call.Args)-1 &&
|
if idx == len(call.Args)-1 &&
|
||||||
fileVersion != "" && // fail open
|
fileVersion != "" && // fail open
|
||||||
versions.AtLeast(fileVersion, "go1.24") {
|
versions.AtLeast(fileVersion, versions.Go1_24) {
|
||||||
|
|
||||||
pass.Report(analysis.Diagnostic{
|
pass.Report(analysis.Diagnostic{
|
||||||
Pos: formatArg.Pos(),
|
Pos: formatArg.Pos(),
|
||||||
|
|
@ -662,7 +662,7 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C
|
||||||
anyIndex = true
|
anyIndex = true
|
||||||
}
|
}
|
||||||
rng := opRange(formatArg, op)
|
rng := opRange(formatArg, op)
|
||||||
if !okPrintfArg(pass, call, rng, &maxArgIndex, firstArg, name, op) {
|
if !okPrintfArg(pass, fileVersion, call, rng, &maxArgIndex, firstArg, name, op) {
|
||||||
// One error per format is enough.
|
// One error per format is enough.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -694,9 +694,9 @@ func checkPrintf(pass *analysis.Pass, fileVersion string, kind Kind, call *ast.C
|
||||||
// such as the position of the %v substring of "...%v...".
|
// such as the position of the %v substring of "...%v...".
|
||||||
func opRange(formatArg ast.Expr, op *fmtstr.Operation) analysis.Range {
|
func opRange(formatArg ast.Expr, op *fmtstr.Operation) analysis.Range {
|
||||||
if lit, ok := formatArg.(*ast.BasicLit); ok {
|
if lit, ok := formatArg.(*ast.BasicLit); ok {
|
||||||
start, end, err := astutil.RangeInStringLiteral(lit, op.Range.Start, op.Range.End)
|
rng, err := astutil.RangeInStringLiteral(lit, op.Range.Start, op.Range.End)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return analysisinternal.Range(start, end) // position of "%v"
|
return rng // position of "%v"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return formatArg // entire format string
|
return formatArg // entire format string
|
||||||
|
|
@ -707,6 +707,7 @@ type printfArgType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
argBool printfArgType = 1 << iota
|
argBool printfArgType = 1 << iota
|
||||||
|
argByte
|
||||||
argInt
|
argInt
|
||||||
argRune
|
argRune
|
||||||
argString
|
argString
|
||||||
|
|
@ -751,7 +752,7 @@ var printVerbs = []printVerb{
|
||||||
{'o', sharpNumFlag, argInt | argPointer},
|
{'o', sharpNumFlag, argInt | argPointer},
|
||||||
{'O', sharpNumFlag, argInt | argPointer},
|
{'O', sharpNumFlag, argInt | argPointer},
|
||||||
{'p', "-#", argPointer},
|
{'p', "-#", argPointer},
|
||||||
{'q', " -+.0#", argRune | argInt | argString},
|
{'q', " -+.0#", argRune | argInt | argString}, // note: when analyzing go1.26 code, argInt => argByte
|
||||||
{'s', " -+.0", argString},
|
{'s', " -+.0", argString},
|
||||||
{'t', "-", argBool},
|
{'t', "-", argBool},
|
||||||
{'T', "-", anyType},
|
{'T', "-", anyType},
|
||||||
|
|
@ -765,7 +766,7 @@ var printVerbs = []printVerb{
|
||||||
// okPrintfArg compares the operation to the arguments actually present,
|
// okPrintfArg compares the operation to the arguments actually present,
|
||||||
// reporting any discrepancies it can discern, maxArgIndex was the index of the highest used index.
|
// reporting any discrepancies it can discern, maxArgIndex was the index of the highest used index.
|
||||||
// If the final argument is ellipsissed, there's little it can do for that.
|
// If the final argument is ellipsissed, there's little it can do for that.
|
||||||
func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, maxArgIndex *int, firstArg int, name string, operation *fmtstr.Operation) (ok bool) {
|
func okPrintfArg(pass *analysis.Pass, fileVersion string, call *ast.CallExpr, rng analysis.Range, maxArgIndex *int, firstArg int, name string, operation *fmtstr.Operation) (ok bool) {
|
||||||
verb := operation.Verb.Verb
|
verb := operation.Verb.Verb
|
||||||
var v printVerb
|
var v printVerb
|
||||||
found := false
|
found := false
|
||||||
|
|
@ -777,6 +778,13 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, ma
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When analyzing go1.26 code, rune and byte are the only %q integers (#72850).
|
||||||
|
if verb == 'q' &&
|
||||||
|
fileVersion != "" && // fail open
|
||||||
|
versions.AtLeast(fileVersion, versions.Go1_26) {
|
||||||
|
v.typ = argRune | argByte | argString
|
||||||
|
}
|
||||||
|
|
||||||
// Could verb's arg implement fmt.Formatter?
|
// Could verb's arg implement fmt.Formatter?
|
||||||
// Skip check for the %w verb, which requires an error.
|
// Skip check for the %w verb, which requires an error.
|
||||||
formatter := false
|
formatter := false
|
||||||
|
|
|
||||||
16
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/types.go
generated
vendored
16
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/types.go
generated
vendored
|
|
@ -204,8 +204,7 @@ func (m *argMatcher) match(typ types.Type, topLevel bool) bool {
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
// report whether all the elements of the struct match the expected type. For
|
// report whether all the elements of the struct match the expected type. For
|
||||||
// instance, with "%d" all the elements must be printable with the "%d" format.
|
// instance, with "%d" all the elements must be printable with the "%d" format.
|
||||||
for i := 0; i < typ.NumFields(); i++ {
|
for typf := range typ.Fields() {
|
||||||
typf := typ.Field(i)
|
|
||||||
if !m.match(typf.Type(), false) {
|
if !m.match(typf.Type(), false) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -228,14 +227,20 @@ func (m *argMatcher) match(typ types.Type, topLevel bool) bool {
|
||||||
types.Bool:
|
types.Bool:
|
||||||
return m.t&argBool != 0
|
return m.t&argBool != 0
|
||||||
|
|
||||||
|
case types.Byte:
|
||||||
|
return m.t&(argInt|argByte) != 0
|
||||||
|
|
||||||
|
case types.Rune, types.UntypedRune:
|
||||||
|
return m.t&(argInt|argRune) != 0
|
||||||
|
|
||||||
case types.UntypedInt,
|
case types.UntypedInt,
|
||||||
types.Int,
|
types.Int,
|
||||||
types.Int8,
|
types.Int8,
|
||||||
types.Int16,
|
types.Int16,
|
||||||
types.Int32,
|
// see case Rune for int32
|
||||||
types.Int64,
|
types.Int64,
|
||||||
types.Uint,
|
types.Uint,
|
||||||
types.Uint8,
|
// see case Byte for uint8
|
||||||
types.Uint16,
|
types.Uint16,
|
||||||
types.Uint32,
|
types.Uint32,
|
||||||
types.Uint64,
|
types.Uint64,
|
||||||
|
|
@ -259,9 +264,6 @@ func (m *argMatcher) match(typ types.Type, topLevel bool) bool {
|
||||||
case types.UnsafePointer:
|
case types.UnsafePointer:
|
||||||
return m.t&(argPointer|argInt) != 0
|
return m.t&(argPointer|argInt) != 0
|
||||||
|
|
||||||
case types.UntypedRune:
|
|
||||||
return m.t&(argInt|argRune) != 0
|
|
||||||
|
|
||||||
case types.UntypedNil:
|
case types.UntypedNil:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/sigchanyzer/sigchanyzer.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/sigchanyzer/sigchanyzer.go
generated
vendored
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ var doc string
|
||||||
// Analyzer describes sigchanyzer analysis function detector.
|
// Analyzer describes sigchanyzer analysis function detector.
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "sigchanyzer",
|
Name: "sigchanyzer",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "sigchanyzer"),
|
Doc: analyzerutil.MustExtractDoc(doc, "sigchanyzer"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/sigchanyzer",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/sigchanyzer",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
|
||||||
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/slog/slog.go
generated
vendored
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/slog/slog.go
generated
vendored
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
@ -29,7 +29,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "slog",
|
Name: "slog",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "slog"),
|
Doc: analyzerutil.MustExtractDoc(doc, "slog"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/slog",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/slog",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
@ -168,7 +168,7 @@ func isAttr(t types.Type) bool {
|
||||||
// "slog.Logger.With" (instead of "(*log/slog.Logger).With")
|
// "slog.Logger.With" (instead of "(*log/slog.Logger).With")
|
||||||
func shortName(fn *types.Func) string {
|
func shortName(fn *types.Func) string {
|
||||||
var r string
|
var r string
|
||||||
if recv := fn.Type().(*types.Signature).Recv(); recv != nil {
|
if recv := fn.Signature().Recv(); recv != nil {
|
||||||
if _, named := typesinternal.ReceiverNamed(recv); named != nil {
|
if _, named := typesinternal.ReceiverNamed(recv); named != nil {
|
||||||
r = named.Obj().Name()
|
r = named.Obj().Name()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -188,7 +188,7 @@ func kvFuncSkipArgs(fn *types.Func) (int, bool) {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
var recvName string // by default a slog package function
|
var recvName string // by default a slog package function
|
||||||
if recv := fn.Type().(*types.Signature).Recv(); recv != nil {
|
if recv := fn.Signature().Recv(); recv != nil {
|
||||||
_, named := typesinternal.ReceiverNamed(recv)
|
_, named := typesinternal.ReceiverNamed(recv)
|
||||||
if named == nil {
|
if named == nil {
|
||||||
return 0, false // anon struct/interface
|
return 0, false // anon struct/interface
|
||||||
|
|
|
||||||
10
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go
generated
vendored
10
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go
generated
vendored
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -21,7 +21,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "stdmethods",
|
Name: "stdmethods",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "stdmethods"),
|
Doc: analyzerutil.MustExtractDoc(doc, "stdmethods"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdmethods",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdmethods",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
@ -131,12 +131,12 @@ func canonicalMethod(pass *analysis.Pass, id *ast.Ident) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the =s (if any) all match?
|
// Do the =s (if any) all match?
|
||||||
if !matchParams(pass, expect.args, args, "=") || !matchParams(pass, expect.results, results, "=") {
|
if !matchParams(expect.args, args, "=") || !matchParams(expect.results, results, "=") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Everything must match.
|
// Everything must match.
|
||||||
if !matchParams(pass, expect.args, args, "") || !matchParams(pass, expect.results, results, "") {
|
if !matchParams(expect.args, args, "") || !matchParams(expect.results, results, "") {
|
||||||
expectFmt := id.Name + "(" + argjoin(expect.args) + ")"
|
expectFmt := id.Name + "(" + argjoin(expect.args) + ")"
|
||||||
if len(expect.results) == 1 {
|
if len(expect.results) == 1 {
|
||||||
expectFmt += " " + argjoin(expect.results)
|
expectFmt += " " + argjoin(expect.results)
|
||||||
|
|
@ -168,7 +168,7 @@ func argjoin(x []string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does each type in expect with the given prefix match the corresponding type in actual?
|
// Does each type in expect with the given prefix match the corresponding type in actual?
|
||||||
func matchParams(pass *analysis.Pass, expect []string, actual *types.Tuple, prefix string) bool {
|
func matchParams(expect []string, actual *types.Tuple, prefix string) bool {
|
||||||
for i, x := range expect {
|
for i, x := range expect {
|
||||||
if !strings.HasPrefix(x, prefix) {
|
if !strings.HasPrefix(x, prefix) {
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go
generated
vendored
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
"golang.org/x/tools/internal/typeparams"
|
"golang.org/x/tools/internal/typeparams"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
|
|
@ -25,7 +25,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "stringintconv",
|
Name: "stringintconv",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "stringintconv"),
|
Doc: analyzerutil.MustExtractDoc(doc, "stringintconv"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stringintconv",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stringintconv",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ func init() {
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "testinggoroutine",
|
Name: "testinggoroutine",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "testinggoroutine"),
|
Doc: analyzerutil.MustExtractDoc(doc, "testinggoroutine"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/testinggoroutine",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/testinggoroutine",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/util.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/util.go
generated
vendored
|
|
@ -36,7 +36,7 @@ func localFunctionDecls(info *types.Info, files []*ast.File) func(*types.Func) *
|
||||||
// isMethodNamed returns true if f is a method defined
|
// isMethodNamed returns true if f is a method defined
|
||||||
// in package with the path pkgPath with a name in names.
|
// in package with the path pkgPath with a name in names.
|
||||||
//
|
//
|
||||||
// (Unlike [analysisinternal.IsMethodNamed], it ignores the receiver type name.)
|
// (Unlike [analysis.IsMethodNamed], it ignores the receiver type name.)
|
||||||
func isMethodNamed(f *types.Func, pkgPath string, names ...string) bool {
|
func isMethodNamed(f *types.Func, pkgPath string, names ...string) bool {
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return false
|
return false
|
||||||
|
|
@ -44,7 +44,7 @@ func isMethodNamed(f *types.Func, pkgPath string, names ...string) bool {
|
||||||
if f.Pkg() == nil || f.Pkg().Path() != pkgPath {
|
if f.Pkg() == nil || f.Pkg().Path() != pkgPath {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if f.Type().(*types.Signature).Recv() == nil {
|
if f.Signature().Recv() == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return slices.Contains(names, f.Name())
|
return slices.Contains(names, f.Name())
|
||||||
|
|
|
||||||
7
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go
generated
vendored
7
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go
generated
vendored
|
|
@ -15,7 +15,8 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
|
"golang.org/x/tools/internal/astutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -24,7 +25,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "tests",
|
Name: "tests",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "tests"),
|
Doc: analyzerutil.MustExtractDoc(doc, "tests"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/tests",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/tests",
|
||||||
Run: run,
|
Run: run,
|
||||||
}
|
}
|
||||||
|
|
@ -464,7 +465,7 @@ func checkTest(pass *analysis.Pass, fn *ast.FuncDecl, prefix string) {
|
||||||
if tparams := fn.Type.TypeParams; tparams != nil && len(tparams.List) > 0 {
|
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.
|
// 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.
|
// We have currently decided to also warn before compilation/package loading. This can help users in IDEs.
|
||||||
pass.ReportRangef(analysisinternal.Range(tparams.Opening, tparams.Closing),
|
pass.ReportRangef(astutil.RangeOf(tparams.Opening, tparams.Closing),
|
||||||
"%s has type parameters: it will not be run by go test as a %sXXX function",
|
"%s has type parameters: it will not be run by go test as a %sXXX function",
|
||||||
fn.Name.Name, prefix)
|
fn.Name.Name, prefix)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/timeformat/timeformat.go
generated
vendored
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/timeformat/timeformat.go
generated
vendored
|
|
@ -18,7 +18,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "timeformat",
|
Name: "timeformat",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "timeformat"),
|
Doc: analyzerutil.MustExtractDoc(doc, "timeformat"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/timeformat",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/timeformat",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
@ -39,7 +39,7 @@ var Analyzer = &analysis.Analyzer{
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
func run(pass *analysis.Pass) (any, error) {
|
||||||
// Note: (time.Time).Format is a method and can be a typeutil.Callee
|
// Note: (time.Time).Format is a method and can be a typeutil.Callee
|
||||||
// without directly importing "time". So we cannot just skip this package
|
// without directly importing "time". So we cannot just skip this package
|
||||||
// when !analysisinternal.Imports(pass.Pkg, "time").
|
// when !analysis.Imports(pass.Pkg, "time").
|
||||||
// TODO(taking): Consider using a prepass to collect typeutil.Callees.
|
// TODO(taking): Consider using a prepass to collect typeutil.Callees.
|
||||||
|
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||||
|
|
|
||||||
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal/unmarshal.go
generated
vendored
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal/unmarshal.go
generated
vendored
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "unmarshal",
|
Name: "unmarshal",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "unmarshal"),
|
Doc: analyzerutil.MustExtractDoc(doc, "unmarshal"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unmarshal",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unmarshal",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
@ -39,7 +39,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
// Note: (*"encoding/json".Decoder).Decode, (* "encoding/gob".Decoder).Decode
|
// Note: (*"encoding/json".Decoder).Decode, (* "encoding/gob".Decoder).Decode
|
||||||
// and (* "encoding/xml".Decoder).Decode are methods and can be a typeutil.Callee
|
// and (* "encoding/xml".Decoder).Decode are methods and can be a typeutil.Callee
|
||||||
// without directly importing their packages. So we cannot just skip this package
|
// without directly importing their packages. So we cannot just skip this package
|
||||||
// when !analysisinternal.Imports(pass.Pkg, "encoding/...").
|
// when !analysis.Imports(pass.Pkg, "encoding/...").
|
||||||
// TODO(taking): Consider using a prepass to collect typeutil.Callees.
|
// TODO(taking): Consider using a prepass to collect typeutil.Callees.
|
||||||
|
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||||
|
|
@ -57,7 +57,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
// Classify the callee (without allocating memory).
|
// Classify the callee (without allocating memory).
|
||||||
argidx := -1
|
argidx := -1
|
||||||
|
|
||||||
recv := fn.Type().(*types.Signature).Recv()
|
recv := fn.Signature().Recv()
|
||||||
if fn.Name() == "Unmarshal" && recv == nil {
|
if fn.Name() == "Unmarshal" && recv == nil {
|
||||||
// "encoding/json".Unmarshal
|
// "encoding/json".Unmarshal
|
||||||
// "encoding/xml".Unmarshal
|
// "encoding/xml".Unmarshal
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unreachable/unreachable.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unreachable/unreachable.go
generated
vendored
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/refactor"
|
"golang.org/x/tools/internal/refactor"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "unreachable",
|
Name: "unreachable",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "unreachable"),
|
Doc: analyzerutil.MustExtractDoc(doc, "unreachable"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unreachable",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unreachable",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
RunDespiteErrors: true,
|
RunDespiteErrors: true,
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unsafeptr/unsafeptr.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unsafeptr/unsafeptr.go
generated
vendored
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "unsafeptr",
|
Name: "unsafeptr",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "unsafeptr"),
|
Doc: analyzerutil.MustExtractDoc(doc, "unsafeptr"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unsafeptr",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unsafeptr",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
|
||||||
11
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go
generated
vendored
11
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go
generated
vendored
|
|
@ -25,7 +25,8 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
|
"golang.org/x/tools/internal/astutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -33,7 +34,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "unusedresult",
|
Name: "unusedresult",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "unusedresult"),
|
Doc: analyzerutil.MustExtractDoc(doc, "unusedresult"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedresult",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedresult",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
@ -149,11 +150,11 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return // e.g. var or builtin
|
return // e.g. var or builtin
|
||||||
}
|
}
|
||||||
if sig := fn.Type().(*types.Signature); sig.Recv() != nil {
|
if sig := fn.Signature(); sig.Recv() != nil {
|
||||||
// method (e.g. foo.String())
|
// method (e.g. foo.String())
|
||||||
if types.Identical(sig, sigNoArgsStringResult) {
|
if types.Identical(sig, sigNoArgsStringResult) {
|
||||||
if stringMethods[fn.Name()] {
|
if stringMethods[fn.Name()] {
|
||||||
pass.ReportRangef(analysisinternal.Range(call.Pos(), call.Lparen),
|
pass.ReportRangef(astutil.RangeOf(call.Pos(), call.Lparen),
|
||||||
"result of (%s).%s call not used",
|
"result of (%s).%s call not used",
|
||||||
sig.Recv().Type(), fn.Name())
|
sig.Recv().Type(), fn.Name())
|
||||||
}
|
}
|
||||||
|
|
@ -161,7 +162,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
} else {
|
} else {
|
||||||
// package-level function (e.g. fmt.Errorf)
|
// package-level function (e.g. fmt.Errorf)
|
||||||
if pkgFuncs[[2]string{fn.Pkg().Path(), fn.Name()}] {
|
if pkgFuncs[[2]string{fn.Pkg().Path(), fn.Name()}] {
|
||||||
pass.ReportRangef(analysisinternal.Range(call.Pos(), call.Lparen),
|
pass.ReportRangef(astutil.RangeOf(call.Pos(), call.Lparen),
|
||||||
"result of %s.%s call not used",
|
"result of %s.%s call not used",
|
||||||
fn.Pkg().Path(), fn.Name())
|
fn.Pkg().Path(), fn.Name())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/waitgroup/waitgroup.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/waitgroup/waitgroup.go
generated
vendored
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/analyzerutil"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "waitgroup",
|
Name: "waitgroup",
|
||||||
Doc: analysisinternal.MustExtractDoc(doc, "waitgroup"),
|
Doc: analyzerutil.MustExtractDoc(doc, "waitgroup"),
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/waitgroup",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/waitgroup",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
|
|
|
||||||
28
src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go
generated
vendored
28
src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go
generated
vendored
|
|
@ -49,7 +49,7 @@ import (
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/internal/analysisflags"
|
"golang.org/x/tools/go/analysis/internal/analysisflags"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysis/driverutil"
|
||||||
"golang.org/x/tools/internal/facts"
|
"golang.org/x/tools/internal/facts"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -183,16 +183,18 @@ func processResults(fset *token.FileSet, id string, results []result) (exit int)
|
||||||
// but apply all fixes from the root actions.
|
// but apply all fixes from the root actions.
|
||||||
|
|
||||||
// Convert results to form needed by ApplyFixes.
|
// Convert results to form needed by ApplyFixes.
|
||||||
fixActions := make([]analysisflags.FixAction, len(results))
|
fixActions := make([]driverutil.FixAction, len(results))
|
||||||
for i, res := range results {
|
for i, res := range results {
|
||||||
fixActions[i] = analysisflags.FixAction{
|
fixActions[i] = driverutil.FixAction{
|
||||||
Name: res.a.Name,
|
Name: res.a.Name,
|
||||||
|
Pkg: res.pkg,
|
||||||
|
Files: res.files,
|
||||||
FileSet: fset,
|
FileSet: fset,
|
||||||
ReadFileFunc: os.ReadFile,
|
ReadFileFunc: os.ReadFile, // TODO(adonovan): respect overlays
|
||||||
Diagnostics: res.diagnostics,
|
Diagnostics: res.diagnostics,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := analysisflags.ApplyFixes(fixActions, false); err != nil {
|
if err := driverutil.ApplyFixes(fixActions, analysisflags.Diff, false); err != nil {
|
||||||
// Fail when applying fixes failed.
|
// Fail when applying fixes failed.
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
exit = 1
|
exit = 1
|
||||||
|
|
@ -209,7 +211,7 @@ func processResults(fset *token.FileSet, id string, results []result) (exit int)
|
||||||
|
|
||||||
if analysisflags.JSON {
|
if analysisflags.JSON {
|
||||||
// JSON output
|
// JSON output
|
||||||
tree := make(analysisflags.JSONTree)
|
tree := make(driverutil.JSONTree)
|
||||||
for _, res := range results {
|
for _, res := range results {
|
||||||
tree.Add(fset, id, res.a.Name, res.diagnostics, res.err)
|
tree.Add(fset, id, res.a.Name, res.diagnostics, res.err)
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +227,7 @@ func processResults(fset *token.FileSet, id string, results []result) (exit int)
|
||||||
}
|
}
|
||||||
for _, res := range results {
|
for _, res := range results {
|
||||||
for _, diag := range res.diagnostics {
|
for _, diag := range res.diagnostics {
|
||||||
analysisflags.PrintPlain(os.Stderr, fset, analysisflags.Context, diag)
|
driverutil.PrintPlain(os.Stderr, fset, analysisflags.Context, diag)
|
||||||
exit = 1
|
exit = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -428,7 +430,7 @@ func run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]re
|
||||||
ResultOf: inputs,
|
ResultOf: inputs,
|
||||||
Report: func(d analysis.Diagnostic) {
|
Report: func(d analysis.Diagnostic) {
|
||||||
// Unitchecker doesn't apply fixes, but it does report them in the JSON output.
|
// Unitchecker doesn't apply fixes, but it does report them in the JSON output.
|
||||||
if err := analysisinternal.ValidateFixes(fset, a, d.SuggestedFixes); err != nil {
|
if err := driverutil.ValidateFixes(fset, a, d.SuggestedFixes); err != nil {
|
||||||
// Since we have diagnostics, the exit code will be nonzero,
|
// Since we have diagnostics, the exit code will be nonzero,
|
||||||
// so logging these errors is sufficient.
|
// so logging these errors is sufficient.
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
|
@ -444,14 +446,14 @@ func run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]re
|
||||||
AllPackageFacts: func() []analysis.PackageFact { return facts.AllPackageFacts(factFilter) },
|
AllPackageFacts: func() []analysis.PackageFact { return facts.AllPackageFacts(factFilter) },
|
||||||
Module: module,
|
Module: module,
|
||||||
}
|
}
|
||||||
pass.ReadFile = analysisinternal.CheckedReadFile(pass, os.ReadFile)
|
pass.ReadFile = driverutil.CheckedReadFile(pass, os.ReadFile)
|
||||||
|
|
||||||
t0 := time.Now()
|
t0 := time.Now()
|
||||||
act.result, act.err = a.Run(pass)
|
act.result, act.err = a.Run(pass)
|
||||||
|
|
||||||
if act.err == nil { // resolve URLs on diagnostics.
|
if act.err == nil { // resolve URLs on diagnostics.
|
||||||
for i := range act.diagnostics {
|
for i := range act.diagnostics {
|
||||||
if url, uerr := analysisflags.ResolveURL(a, act.diagnostics[i]); uerr == nil {
|
if url, uerr := driverutil.ResolveURL(a, act.diagnostics[i]); uerr == nil {
|
||||||
act.diagnostics[i].URL = url
|
act.diagnostics[i].URL = url
|
||||||
} else {
|
} else {
|
||||||
act.err = uerr // keep the last error
|
act.err = uerr // keep the last error
|
||||||
|
|
@ -482,9 +484,7 @@ func run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]re
|
||||||
results := make([]result, len(analyzers))
|
results := make([]result, len(analyzers))
|
||||||
for i, a := range analyzers {
|
for i, a := range analyzers {
|
||||||
act := actions[a]
|
act := actions[a]
|
||||||
results[i].a = a
|
results[i] = result{pkg, files, a, act.diagnostics, act.err}
|
||||||
results[i].err = act.err
|
|
||||||
results[i].diagnostics = act.diagnostics
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data := facts.Encode()
|
data := facts.Encode()
|
||||||
|
|
@ -499,6 +499,8 @@ func run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]re
|
||||||
}
|
}
|
||||||
|
|
||||||
type result struct {
|
type result struct {
|
||||||
|
pkg *types.Package
|
||||||
|
files []*ast.File
|
||||||
a *analysis.Analyzer
|
a *analysis.Analyzer
|
||||||
diagnostics []analysis.Diagnostic
|
diagnostics []analysis.Diagnostic
|
||||||
err error
|
err error
|
||||||
|
|
|
||||||
17
src/cmd/vendor/golang.org/x/tools/go/ast/inspector/cursor.go
generated
vendored
17
src/cmd/vendor/golang.org/x/tools/go/ast/inspector/cursor.go
generated
vendored
|
|
@ -467,7 +467,9 @@ func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) {
|
||||||
// This algorithm could be implemented using c.Inspect,
|
// This algorithm could be implemented using c.Inspect,
|
||||||
// but it is about 2.5x slower.
|
// but it is about 2.5x slower.
|
||||||
|
|
||||||
best := int32(-1) // push index of latest (=innermost) node containing range
|
// best is the push-index of the latest (=innermost) node containing range.
|
||||||
|
// (Beware: latest is not always innermost because FuncDecl.{Name,Type} overlap.)
|
||||||
|
best := int32(-1)
|
||||||
for i, limit := c.indices(); i < limit; i++ {
|
for i, limit := c.indices(); i < limit; i++ {
|
||||||
ev := events[i]
|
ev := events[i]
|
||||||
if ev.index > i { // push?
|
if ev.index > i { // push?
|
||||||
|
|
@ -481,6 +483,19 @@ func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Edge case: FuncDecl.Name and .Type overlap:
|
||||||
|
// Don't update best from Name to FuncDecl.Type.
|
||||||
|
//
|
||||||
|
// The condition can be read as:
|
||||||
|
// - n is FuncType
|
||||||
|
// - n.parent is FuncDecl
|
||||||
|
// - best is strictly beneath the FuncDecl
|
||||||
|
if ev.typ == 1<<nFuncType &&
|
||||||
|
events[ev.parent].typ == 1<<nFuncDecl &&
|
||||||
|
best > ev.parent {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
nodeEnd = n.End()
|
nodeEnd = n.End()
|
||||||
if n.Pos() > start {
|
if n.Pos() > start {
|
||||||
break // disjoint, after; stop
|
break // disjoint, after; stop
|
||||||
|
|
|
||||||
16
src/cmd/vendor/golang.org/x/tools/go/cfg/builder.go
generated
vendored
16
src/cmd/vendor/golang.org/x/tools/go/cfg/builder.go
generated
vendored
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type builder struct {
|
type builder struct {
|
||||||
cfg *CFG
|
blocks []*Block
|
||||||
mayReturn func(*ast.CallExpr) bool
|
mayReturn func(*ast.CallExpr) bool
|
||||||
current *Block
|
current *Block
|
||||||
lblocks map[string]*lblock // labeled blocks
|
lblocks map[string]*lblock // labeled blocks
|
||||||
|
|
@ -32,12 +32,18 @@ start:
|
||||||
*ast.SendStmt,
|
*ast.SendStmt,
|
||||||
*ast.IncDecStmt,
|
*ast.IncDecStmt,
|
||||||
*ast.GoStmt,
|
*ast.GoStmt,
|
||||||
*ast.DeferStmt,
|
|
||||||
*ast.EmptyStmt,
|
*ast.EmptyStmt,
|
||||||
*ast.AssignStmt:
|
*ast.AssignStmt:
|
||||||
// No effect on control flow.
|
// No effect on control flow.
|
||||||
b.add(s)
|
b.add(s)
|
||||||
|
|
||||||
|
case *ast.DeferStmt:
|
||||||
|
b.add(s)
|
||||||
|
// Assume conservatively that this behaves like:
|
||||||
|
// defer func() { recover() }
|
||||||
|
// so any subsequent panic may act like a return.
|
||||||
|
b.current.returns = true
|
||||||
|
|
||||||
case *ast.ExprStmt:
|
case *ast.ExprStmt:
|
||||||
b.add(s)
|
b.add(s)
|
||||||
if call, ok := s.X.(*ast.CallExpr); ok && !b.mayReturn(call) {
|
if call, ok := s.X.(*ast.CallExpr); ok && !b.mayReturn(call) {
|
||||||
|
|
@ -64,6 +70,7 @@ start:
|
||||||
goto start // effectively: tailcall stmt(g, s.Stmt, label)
|
goto start // effectively: tailcall stmt(g, s.Stmt, label)
|
||||||
|
|
||||||
case *ast.ReturnStmt:
|
case *ast.ReturnStmt:
|
||||||
|
b.current.returns = true
|
||||||
b.add(s)
|
b.add(s)
|
||||||
b.current = b.newBlock(KindUnreachable, s)
|
b.current = b.newBlock(KindUnreachable, s)
|
||||||
|
|
||||||
|
|
@ -483,14 +490,13 @@ func (b *builder) labeledBlock(label *ast.Ident, stmt *ast.LabeledStmt) *lblock
|
||||||
// It does not automatically become the current block.
|
// It does not automatically become the current block.
|
||||||
// comment is an optional string for more readable debugging output.
|
// comment is an optional string for more readable debugging output.
|
||||||
func (b *builder) newBlock(kind BlockKind, stmt ast.Stmt) *Block {
|
func (b *builder) newBlock(kind BlockKind, stmt ast.Stmt) *Block {
|
||||||
g := b.cfg
|
|
||||||
block := &Block{
|
block := &Block{
|
||||||
Index: int32(len(g.Blocks)),
|
Index: int32(len(b.blocks)),
|
||||||
Kind: kind,
|
Kind: kind,
|
||||||
Stmt: stmt,
|
Stmt: stmt,
|
||||||
}
|
}
|
||||||
block.Succs = block.succs2[:0]
|
block.Succs = block.succs2[:0]
|
||||||
g.Blocks = append(g.Blocks, block)
|
b.blocks = append(b.blocks, block)
|
||||||
return block
|
return block
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
54
src/cmd/vendor/golang.org/x/tools/go/cfg/cfg.go
generated
vendored
54
src/cmd/vendor/golang.org/x/tools/go/cfg/cfg.go
generated
vendored
|
|
@ -47,13 +47,16 @@ import (
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/format"
|
"go/format"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/cfginternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A CFG represents the control-flow graph of a single function.
|
// A CFG represents the control-flow graph of a single function.
|
||||||
//
|
//
|
||||||
// The entry point is Blocks[0]; there may be multiple return blocks.
|
// The entry point is Blocks[0]; there may be multiple return blocks.
|
||||||
type CFG struct {
|
type CFG struct {
|
||||||
Blocks []*Block // block[0] is entry; order otherwise undefined
|
Blocks []*Block // block[0] is entry; order otherwise undefined
|
||||||
|
noreturn bool // function body lacks a reachable return statement
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Block represents a basic block: a list of statements and
|
// A Block represents a basic block: a list of statements and
|
||||||
|
|
@ -67,12 +70,13 @@ type CFG struct {
|
||||||
// an [ast.Expr], Succs[0] is the successor if the condition is true, and
|
// an [ast.Expr], Succs[0] is the successor if the condition is true, and
|
||||||
// Succs[1] is the successor if the condition is false.
|
// Succs[1] is the successor if the condition is false.
|
||||||
type Block struct {
|
type Block struct {
|
||||||
Nodes []ast.Node // statements, expressions, and ValueSpecs
|
Nodes []ast.Node // statements, expressions, and ValueSpecs
|
||||||
Succs []*Block // successor nodes in the graph
|
Succs []*Block // successor nodes in the graph
|
||||||
Index int32 // index within CFG.Blocks
|
Index int32 // index within CFG.Blocks
|
||||||
Live bool // block is reachable from entry
|
Live bool // block is reachable from entry
|
||||||
Kind BlockKind // block kind
|
returns bool // block contains return or defer (which may recover and return)
|
||||||
Stmt ast.Stmt // statement that gave rise to this block (see BlockKind for details)
|
Kind BlockKind // block kind
|
||||||
|
Stmt ast.Stmt // statement that gave rise to this block (see BlockKind for details)
|
||||||
|
|
||||||
succs2 [2]*Block // underlying array for Succs
|
succs2 [2]*Block // underlying array for Succs
|
||||||
}
|
}
|
||||||
|
|
@ -141,14 +145,14 @@ func (kind BlockKind) String() string {
|
||||||
func New(body *ast.BlockStmt, mayReturn func(*ast.CallExpr) bool) *CFG {
|
func New(body *ast.BlockStmt, mayReturn func(*ast.CallExpr) bool) *CFG {
|
||||||
b := builder{
|
b := builder{
|
||||||
mayReturn: mayReturn,
|
mayReturn: mayReturn,
|
||||||
cfg: new(CFG),
|
|
||||||
}
|
}
|
||||||
b.current = b.newBlock(KindBody, body)
|
b.current = b.newBlock(KindBody, body)
|
||||||
b.stmt(body)
|
b.stmt(body)
|
||||||
|
|
||||||
// Compute liveness (reachability from entry point), breadth-first.
|
// Compute liveness (reachability from entry point),
|
||||||
q := make([]*Block, 0, len(b.cfg.Blocks))
|
// breadth-first, marking Block.Live flags.
|
||||||
q = append(q, b.cfg.Blocks[0]) // entry point
|
q := make([]*Block, 0, len(b.blocks))
|
||||||
|
q = append(q, b.blocks[0]) // entry point
|
||||||
for len(q) > 0 {
|
for len(q) > 0 {
|
||||||
b := q[len(q)-1]
|
b := q[len(q)-1]
|
||||||
q = q[:len(q)-1]
|
q = q[:len(q)-1]
|
||||||
|
|
@ -162,12 +166,30 @@ func New(body *ast.BlockStmt, mayReturn func(*ast.CallExpr) bool) *CFG {
|
||||||
// Does control fall off the end of the function's body?
|
// Does control fall off the end of the function's body?
|
||||||
// Make implicit return explicit.
|
// Make implicit return explicit.
|
||||||
if b.current != nil && b.current.Live {
|
if b.current != nil && b.current.Live {
|
||||||
|
b.current.returns = true
|
||||||
b.add(&ast.ReturnStmt{
|
b.add(&ast.ReturnStmt{
|
||||||
Return: body.End() - 1,
|
Return: body.End() - 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.cfg
|
// Is any return (or defer+recover) block reachable?
|
||||||
|
noreturn := true
|
||||||
|
for _, bl := range b.blocks {
|
||||||
|
if bl.Live && bl.returns {
|
||||||
|
noreturn = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &CFG{Blocks: b.blocks, noreturn: noreturn}
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNoReturn reports whether the function has no reachable return.
|
||||||
|
// TODO(adonovan): add (*CFG).NoReturn to public API.
|
||||||
|
func isNoReturn(_cfg any) bool { return _cfg.(*CFG).noreturn }
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cfginternal.IsNoReturn = isNoReturn // expose to ctrlflow analyzer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Block) String() string {
|
func (b *Block) String() string {
|
||||||
|
|
@ -187,6 +209,14 @@ func (b *Block) comment(fset *token.FileSet) string {
|
||||||
//
|
//
|
||||||
// When control falls off the end of the function, the ReturnStmt is synthetic
|
// When control falls off the end of the function, the ReturnStmt is synthetic
|
||||||
// and its [ast.Node.End] position may be beyond the end of the file.
|
// and its [ast.Node.End] position may be beyond the end of the file.
|
||||||
|
//
|
||||||
|
// A function that contains no return statement (explicit or implied)
|
||||||
|
// may yet return normally, and may even return a nonzero value. For example:
|
||||||
|
//
|
||||||
|
// func() (res any) {
|
||||||
|
// defer func() { res = recover() }()
|
||||||
|
// panic(123)
|
||||||
|
// }
|
||||||
func (b *Block) Return() (ret *ast.ReturnStmt) {
|
func (b *Block) Return() (ret *ast.ReturnStmt) {
|
||||||
if len(b.Nodes) > 0 {
|
if len(b.Nodes) > 0 {
|
||||||
ret, _ = b.Nodes[len(b.Nodes)-1].(*ast.ReturnStmt)
|
ret, _ = b.Nodes[len(b.Nodes)-1].(*ast.ReturnStmt)
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
generated
vendored
|
|
@ -249,7 +249,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
|
||||||
|
|
||||||
case *types.Func:
|
case *types.Func:
|
||||||
// A func, if not package-level, must be a method.
|
// A func, if not package-level, must be a method.
|
||||||
if recv := obj.Type().(*types.Signature).Recv(); recv == nil {
|
if recv := obj.Signature().Recv(); recv == nil {
|
||||||
return "", fmt.Errorf("func is not a method: %v", obj)
|
return "", fmt.Errorf("func is not a method: %v", obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -405,7 +405,7 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
_, named := typesinternal.ReceiverNamed(meth.Type().(*types.Signature).Recv())
|
_, named := typesinternal.ReceiverNamed(meth.Signature().Recv())
|
||||||
if named == nil {
|
if named == nil {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3
src/cmd/vendor/golang.org/x/tools/go/types/typeutil/map.go
generated
vendored
3
src/cmd/vendor/golang.org/x/tools/go/types/typeutil/map.go
generated
vendored
|
|
@ -304,8 +304,7 @@ func (h hasher) hash(t types.Type) uint32 {
|
||||||
case *types.Named:
|
case *types.Named:
|
||||||
hash := h.hashTypeName(t.Obj())
|
hash := h.hashTypeName(t.Obj())
|
||||||
targs := t.TypeArgs()
|
targs := t.TypeArgs()
|
||||||
for i := 0; i < targs.Len(); i++ {
|
for targ := range targs.Types() {
|
||||||
targ := targs.At(i)
|
|
||||||
hash += 2 * h.hash(targ)
|
hash += 2 * h.hash(targ)
|
||||||
}
|
}
|
||||||
return hash
|
return hash
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/tools/internal/analysis/analyzerutil/doc.go
generated
vendored
Normal file
6
src/cmd/vendor/golang.org/x/tools/internal/analysis/analyzerutil/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
// Copyright 2025 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 analyzerutil provides implementation helpers for analyzers.
|
||||||
|
package analyzerutil
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package analysisinternal
|
package analyzerutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -35,7 +35,7 @@ import (
|
||||||
//
|
//
|
||||||
// var Analyzer = &analysis.Analyzer{
|
// var Analyzer = &analysis.Analyzer{
|
||||||
// Name: "halting",
|
// Name: "halting",
|
||||||
// Doc: analysisinternal.MustExtractDoc(doc, "halting"),
|
// Doc: analyzerutil.MustExtractDoc(doc, "halting"),
|
||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
func MustExtractDoc(content, name string) string {
|
func MustExtractDoc(content, name string) string {
|
||||||
30
src/cmd/vendor/golang.org/x/tools/internal/analysis/analyzerutil/readfile.go
generated
vendored
Normal file
30
src/cmd/vendor/golang.org/x/tools/internal/analysis/analyzerutil/readfile.go
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2025 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 analyzerutil
|
||||||
|
|
||||||
|
// This file defines helpers for calling [analysis.Pass.ReadFile].
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/token"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadFile reads a file and adds it to the FileSet in pass
|
||||||
|
// so that we can report errors against it using lineStart.
|
||||||
|
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 := pass.Fset.AddFile(filename, -1, len(content))
|
||||||
|
tf.SetLinesForContent(content)
|
||||||
|
return content, tf, nil
|
||||||
|
}
|
||||||
42
src/cmd/vendor/golang.org/x/tools/internal/analysis/analyzerutil/version.go
generated
vendored
Normal file
42
src/cmd/vendor/golang.org/x/tools/internal/analysis/analyzerutil/version.go
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright 2025 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 analyzerutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
"golang.org/x/tools/internal/packagepath"
|
||||||
|
"golang.org/x/tools/internal/stdlib"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileUsesGoVersion reports whether the specified file may use features of the
|
||||||
|
// specified version of Go (e.g. "go1.24").
|
||||||
|
//
|
||||||
|
// Tip: we recommend using this check "late", just before calling
|
||||||
|
// pass.Report, rather than "early" (when entering each ast.File, or
|
||||||
|
// each candidate node of interest, during the traversal), because the
|
||||||
|
// operation is not free, yet is not a highly selective filter: the
|
||||||
|
// fraction of files that pass most version checks is high and
|
||||||
|
// increases over time.
|
||||||
|
func FileUsesGoVersion(pass *analysis.Pass, file *ast.File, version string) (_res bool) {
|
||||||
|
fileVersion := pass.TypesInfo.FileVersions[file]
|
||||||
|
|
||||||
|
// Standard packages that are part of toolchain bootstrapping
|
||||||
|
// are not considered to use a version of Go later than the
|
||||||
|
// current bootstrap toolchain version.
|
||||||
|
// The bootstrap rule does not cover tests,
|
||||||
|
// and some tests (e.g. debug/elf/file_test.go) rely on this.
|
||||||
|
pkgpath := pass.Pkg.Path()
|
||||||
|
if packagepath.IsStdPackage(pkgpath) &&
|
||||||
|
stdlib.IsBootstrapPackage(pkgpath) && // (excludes "*_test" external test packages)
|
||||||
|
!strings.HasSuffix(pass.Fset.File(file.Pos()).Name(), "_test.go") { // (excludes all tests)
|
||||||
|
fileVersion = stdlib.BootstrapVersion.String() // package must bootstrap
|
||||||
|
}
|
||||||
|
|
||||||
|
return !versions.Before(fileVersion, version)
|
||||||
|
}
|
||||||
|
|
@ -2,37 +2,48 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package analysisflags
|
// Package driverutil defines implementation helper functions for
|
||||||
|
// analysis drivers such as unitchecker, {single,multi}checker, and
|
||||||
|
// analysistest.
|
||||||
|
package driverutil
|
||||||
|
|
||||||
// This file defines the -fix logic common to unitchecker and
|
// This file defines the -fix logic common to unitchecker and
|
||||||
// {single,multi}checker.
|
// {single,multi}checker.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/format"
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/printer"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"go/types"
|
||||||
"log"
|
"log"
|
||||||
"maps"
|
"maps"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/go/ast/astutil"
|
||||||
|
"golang.org/x/tools/internal/astutil/free"
|
||||||
"golang.org/x/tools/internal/diff"
|
"golang.org/x/tools/internal/diff"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FixAction abstracts a checker action (running one analyzer on one
|
// FixAction abstracts a checker action (running one analyzer on one
|
||||||
// package) for the purposes of applying its diagnostics' fixes.
|
// package) for the purposes of applying its diagnostics' fixes.
|
||||||
type FixAction struct {
|
type FixAction struct {
|
||||||
Name string // e.g. "analyzer@package"
|
Name string // e.g. "analyzer@package"
|
||||||
|
Pkg *types.Package // (for import removal)
|
||||||
|
Files []*ast.File
|
||||||
FileSet *token.FileSet
|
FileSet *token.FileSet
|
||||||
ReadFileFunc analysisinternal.ReadFileFunc
|
ReadFileFunc ReadFileFunc
|
||||||
Diagnostics []analysis.Diagnostic
|
Diagnostics []analysis.Diagnostic
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplyFixes attempts to apply the first suggested fix associated
|
// ApplyFixes attempts to apply the first suggested fix associated
|
||||||
// with each diagnostic reported by the specified actions.
|
// with each diagnostic reported by the specified actions.
|
||||||
// All fixes must have been validated by [analysisinternal.ValidateFixes].
|
// All fixes must have been validated by [ValidateFixes].
|
||||||
//
|
//
|
||||||
// Each fix is treated as an independent change; fixes are merged in
|
// Each fix is treated as an independent change; fixes are merged in
|
||||||
// an arbitrary deterministic order as if by a three-way diff tool
|
// an arbitrary deterministic order as if by a three-way diff tool
|
||||||
|
|
@ -58,15 +69,15 @@ type FixAction struct {
|
||||||
// composition of the two fixes is semantically correct. Coalescing
|
// composition of the two fixes is semantically correct. Coalescing
|
||||||
// identical edits is appropriate for imports, but not for, say,
|
// identical edits is appropriate for imports, but not for, say,
|
||||||
// increments to a counter variable; the correct resolution in that
|
// increments to a counter variable; the correct resolution in that
|
||||||
// case might be to increment it twice. Or consider two fixes that
|
// case might be to increment it twice.
|
||||||
// each delete the penultimate reference to an import or local
|
//
|
||||||
// variable: each fix is sound individually, and they may be textually
|
// Or consider two fixes that each delete the penultimate reference to
|
||||||
// distant from each other, but when both are applied, the program is
|
// a local variable: each fix is sound individually, and they may be
|
||||||
// no longer valid because it has an unreferenced import or local
|
// textually distant from each other, but when both are applied, the
|
||||||
// variable.
|
// program is no longer valid because it has an unreferenced local
|
||||||
// TODO(adonovan): investigate replacing the final "gofmt" step with a
|
// variable. (ApplyFixes solves the analogous problem for imports by
|
||||||
// formatter that applies the unused-import deletion logic of
|
// eliminating imports whose name is unreferenced in the remainder of
|
||||||
// "goimports".
|
// the fixed file.)
|
||||||
//
|
//
|
||||||
// Merging depends on both the order of fixes and they order of edits
|
// Merging depends on both the order of fixes and they order of edits
|
||||||
// within them. For example, if three fixes add import "a" twice and
|
// within them. For example, if three fixes add import "a" twice and
|
||||||
|
|
@ -80,12 +91,15 @@ type FixAction struct {
|
||||||
// applyFixes returns success if all fixes are valid, could be cleanly
|
// applyFixes returns success if all fixes are valid, could be cleanly
|
||||||
// merged, and the corresponding files were successfully updated.
|
// merged, and the corresponding files were successfully updated.
|
||||||
//
|
//
|
||||||
// If the -diff flag was set, instead of updating the files it display the final
|
// If printDiff (from the -diff flag) is set, instead of updating the
|
||||||
// patch composed of all the cleanly merged fixes.
|
// files it display the final patch composed of all the cleanly merged
|
||||||
|
// fixes.
|
||||||
//
|
//
|
||||||
// TODO(adonovan): handle file-system level aliases such as symbolic
|
// TODO(adonovan): handle file-system level aliases such as symbolic
|
||||||
// links using robustio.FileID.
|
// links using robustio.FileID.
|
||||||
func ApplyFixes(actions []FixAction, verbose bool) error {
|
func ApplyFixes(actions []FixAction, printDiff, verbose bool) error {
|
||||||
|
generated := make(map[*token.File]bool)
|
||||||
|
|
||||||
// Select fixes to apply.
|
// Select fixes to apply.
|
||||||
//
|
//
|
||||||
// If there are several for a given Diagnostic, choose the first.
|
// If there are several for a given Diagnostic, choose the first.
|
||||||
|
|
@ -96,6 +110,15 @@ func ApplyFixes(actions []FixAction, verbose bool) error {
|
||||||
}
|
}
|
||||||
var fixes []*fixact
|
var fixes []*fixact
|
||||||
for _, act := range actions {
|
for _, act := range actions {
|
||||||
|
for _, file := range act.Files {
|
||||||
|
tokFile := act.FileSet.File(file.FileStart)
|
||||||
|
// Memoize, since there may be many actions
|
||||||
|
// for the same package (list of files).
|
||||||
|
if _, seen := generated[tokFile]; !seen {
|
||||||
|
generated[tokFile] = ast.IsGenerated(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, diag := range act.Diagnostics {
|
for _, diag := range act.Diagnostics {
|
||||||
for i := range diag.SuggestedFixes {
|
for i := range diag.SuggestedFixes {
|
||||||
fix := &diag.SuggestedFixes[i]
|
fix := &diag.SuggestedFixes[i]
|
||||||
|
|
@ -119,7 +142,7 @@ func ApplyFixes(actions []FixAction, verbose bool) error {
|
||||||
// packages are not disjoint, due to test variants, so this
|
// packages are not disjoint, due to test variants, so this
|
||||||
// would not really address the issue.)
|
// would not really address the issue.)
|
||||||
baselineContent := make(map[string][]byte)
|
baselineContent := make(map[string][]byte)
|
||||||
getBaseline := func(readFile analysisinternal.ReadFileFunc, filename string) ([]byte, error) {
|
getBaseline := func(readFile ReadFileFunc, filename string) ([]byte, error) {
|
||||||
content, ok := baselineContent[filename]
|
content, ok := baselineContent[filename]
|
||||||
if !ok {
|
if !ok {
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -134,16 +157,32 @@ func ApplyFixes(actions []FixAction, verbose bool) error {
|
||||||
|
|
||||||
// Apply each fix, updating the current state
|
// Apply each fix, updating the current state
|
||||||
// only if the entire fix can be cleanly merged.
|
// only if the entire fix can be cleanly merged.
|
||||||
accumulatedEdits := make(map[string][]diff.Edit)
|
var (
|
||||||
goodFixes := 0
|
accumulatedEdits = make(map[string][]diff.Edit)
|
||||||
|
filePkgs = make(map[string]*types.Package) // maps each file to an arbitrary package that includes it
|
||||||
|
|
||||||
|
goodFixes = 0 // number of fixes cleanly applied
|
||||||
|
skippedFixes = 0 // number of fixes skipped (because e.g. edits a generated file)
|
||||||
|
)
|
||||||
fixloop:
|
fixloop:
|
||||||
for _, fixact := range fixes {
|
for _, fixact := range fixes {
|
||||||
|
// Skip a fix if any of its edits touch a generated file.
|
||||||
|
for _, edit := range fixact.fix.TextEdits {
|
||||||
|
file := fixact.act.FileSet.File(edit.Pos)
|
||||||
|
if generated[file] {
|
||||||
|
skippedFixes++
|
||||||
|
continue fixloop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Convert analysis.TextEdits to diff.Edits, grouped by file.
|
// Convert analysis.TextEdits to diff.Edits, grouped by file.
|
||||||
// Precondition: a prior call to validateFix succeeded.
|
// Precondition: a prior call to validateFix succeeded.
|
||||||
fileEdits := make(map[string][]diff.Edit)
|
fileEdits := make(map[string][]diff.Edit)
|
||||||
for _, edit := range fixact.fix.TextEdits {
|
for _, edit := range fixact.fix.TextEdits {
|
||||||
file := fixact.act.FileSet.File(edit.Pos)
|
file := fixact.act.FileSet.File(edit.Pos)
|
||||||
|
|
||||||
|
filePkgs[file.Name()] = fixact.act.Pkg
|
||||||
|
|
||||||
baseline, err := getBaseline(fixact.act.ReadFileFunc, file.Name())
|
baseline, err := getBaseline(fixact.act.ReadFileFunc, file.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("skipping fix to file %s: %v", file.Name(), err)
|
log.Printf("skipping fix to file %s: %v", file.Name(), err)
|
||||||
|
|
@ -191,7 +230,7 @@ fixloop:
|
||||||
log.Printf("%s: fix %s applied", fixact.act.Name, fixact.fix.Message)
|
log.Printf("%s: fix %s applied", fixact.act.Name, fixact.fix.Message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
badFixes := len(fixes) - goodFixes
|
badFixes := len(fixes) - goodFixes - skippedFixes // number of fixes that could not be applied
|
||||||
|
|
||||||
// Show diff or update files to final state.
|
// Show diff or update files to final state.
|
||||||
var files []string
|
var files []string
|
||||||
|
|
@ -214,11 +253,11 @@ fixloop:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to format each file.
|
// Attempt to format each file.
|
||||||
if formatted, err := format.Source(final); err == nil {
|
if formatted, err := FormatSourceRemoveImports(filePkgs[file], final); err == nil {
|
||||||
final = formatted
|
final = formatted
|
||||||
}
|
}
|
||||||
|
|
||||||
if diffFlag {
|
if printDiff {
|
||||||
// Since we formatted the file, we need to recompute the diff.
|
// Since we formatted the file, we need to recompute the diff.
|
||||||
unified := diff.Unified(file+" (old)", file+" (new)", string(baseline), string(final))
|
unified := diff.Unified(file+" (old)", file+" (new)", string(baseline), string(final))
|
||||||
// TODO(adonovan): abstract the I/O.
|
// TODO(adonovan): abstract the I/O.
|
||||||
|
|
@ -262,23 +301,149 @@ fixloop:
|
||||||
// These numbers are potentially misleading:
|
// These numbers are potentially misleading:
|
||||||
// The denominator includes duplicate conflicting fixes due to
|
// The denominator includes duplicate conflicting fixes due to
|
||||||
// common files in packages "p" and "p [p.test]", which may
|
// common files in packages "p" and "p [p.test]", which may
|
||||||
// have been fixed fixed and won't appear in the re-run.
|
// have been fixed and won't appear in the re-run.
|
||||||
// TODO(adonovan): eliminate identical fixes as an initial
|
// TODO(adonovan): eliminate identical fixes as an initial
|
||||||
// filtering step.
|
// filtering step.
|
||||||
//
|
//
|
||||||
// TODO(adonovan): should we log that n files were updated in case of total victory?
|
// TODO(adonovan): should we log that n files were updated in case of total victory?
|
||||||
if badFixes > 0 || filesUpdated < totalFiles {
|
if badFixes > 0 || filesUpdated < totalFiles {
|
||||||
if diffFlag {
|
if printDiff {
|
||||||
return fmt.Errorf("%d of %d fixes skipped (e.g. due to conflicts)", badFixes, len(fixes))
|
return fmt.Errorf("%d of %s skipped (e.g. due to conflicts)",
|
||||||
|
badFixes,
|
||||||
|
plural(len(fixes), "fix", "fixes"))
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("applied %d of %d fixes; %d files updated. (Re-run the command to apply more.)",
|
return fmt.Errorf("applied %d of %s; %s updated. (Re-run the command to apply more.)",
|
||||||
goodFixes, len(fixes), filesUpdated)
|
goodFixes,
|
||||||
|
plural(len(fixes), "fix", "fixes"),
|
||||||
|
plural(filesUpdated, "file", "files"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
log.Printf("applied %d fixes, updated %d files", len(fixes), filesUpdated)
|
if skippedFixes > 0 {
|
||||||
|
log.Printf("skipped %s that would edit generated files",
|
||||||
|
plural(skippedFixes, "fix", "fixes"))
|
||||||
|
}
|
||||||
|
log.Printf("applied %s, updated %s",
|
||||||
|
plural(len(fixes), "fix", "fixes"),
|
||||||
|
plural(filesUpdated, "file", "files"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FormatSourceRemoveImports is a variant of [format.Source] that
|
||||||
|
// removes imports that became redundant when fixes were applied.
|
||||||
|
//
|
||||||
|
// Import removal is necessarily heuristic since we do not have type
|
||||||
|
// information for the fixed file and thus cannot accurately tell
|
||||||
|
// whether k is among the free names of T{k: 0}, which requires
|
||||||
|
// knowledge of whether T is a struct type.
|
||||||
|
func FormatSourceRemoveImports(pkg *types.Package, src []byte) ([]byte, error) {
|
||||||
|
// This function was reduced from the "strict entire file"
|
||||||
|
// path through [format.Source].
|
||||||
|
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
file, err := parser.ParseFile(fset, "fixed.go", src, parser.ParseComments|parser.SkipObjectResolution)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ast.SortImports(fset, file)
|
||||||
|
|
||||||
|
removeUnneededImports(fset, pkg, file)
|
||||||
|
|
||||||
|
// printerNormalizeNumbers means to canonicalize number literal prefixes
|
||||||
|
// and exponents while printing. See https://golang.org/doc/go1.13#gofmt.
|
||||||
|
//
|
||||||
|
// This value is defined in go/printer specifically for go/format and cmd/gofmt.
|
||||||
|
const printerNormalizeNumbers = 1 << 30
|
||||||
|
cfg := &printer.Config{
|
||||||
|
Mode: printer.UseSpaces | printer.TabIndent | printerNormalizeNumbers,
|
||||||
|
Tabwidth: 8,
|
||||||
|
}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := cfg.Fprint(&buf, fset, file); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeUnneededImports removes import specs that are not referenced
|
||||||
|
// within the fixed file. It uses [free.Names] to heuristically
|
||||||
|
// approximate the set of imported names needed by the body of the
|
||||||
|
// file based only on syntax.
|
||||||
|
//
|
||||||
|
// pkg provides type information about the unmodified package, in
|
||||||
|
// particular the name that would implicitly be declared by a
|
||||||
|
// non-renaming import of a given existing dependency.
|
||||||
|
func removeUnneededImports(fset *token.FileSet, pkg *types.Package, file *ast.File) {
|
||||||
|
// Map each existing dependency to its default import name.
|
||||||
|
// (We'll need this to interpret non-renaming imports.)
|
||||||
|
packageNames := make(map[string]string)
|
||||||
|
for _, imp := range pkg.Imports() {
|
||||||
|
packageNames[imp.Path()] = imp.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the set of free names of the file,
|
||||||
|
// ignoring its import decls.
|
||||||
|
freenames := make(map[string]bool)
|
||||||
|
for _, decl := range file.Decls {
|
||||||
|
if decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.IMPORT {
|
||||||
|
continue // skip import
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(adonovan): we could do better than includeComplitIdents=false
|
||||||
|
// since we have type information about the unmodified package,
|
||||||
|
// which is a good source of heuristics.
|
||||||
|
const includeComplitIdents = false
|
||||||
|
maps.Copy(freenames, free.Names(decl, includeComplitIdents))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether each import's declared name is free (referenced) by the file.
|
||||||
|
var deletions []func()
|
||||||
|
for _, spec := range file.Imports {
|
||||||
|
path, err := strconv.Unquote(spec.Path.Value)
|
||||||
|
if err != nil {
|
||||||
|
continue // malformed import; ignore
|
||||||
|
}
|
||||||
|
explicit := "" // explicit PkgName, if any
|
||||||
|
if spec.Name != nil {
|
||||||
|
explicit = spec.Name.Name
|
||||||
|
}
|
||||||
|
name := explicit // effective PkgName
|
||||||
|
if name == "" {
|
||||||
|
// Non-renaming import: use package's default name.
|
||||||
|
name = packageNames[path]
|
||||||
|
}
|
||||||
|
switch name {
|
||||||
|
case "":
|
||||||
|
continue // assume it's a new import
|
||||||
|
case ".":
|
||||||
|
continue // dot imports are tricky
|
||||||
|
case "_":
|
||||||
|
continue // keep blank imports
|
||||||
|
}
|
||||||
|
if !freenames[name] {
|
||||||
|
// Import's effective name is not free in (not used by) the file.
|
||||||
|
// Enqueue it for deletion after the loop.
|
||||||
|
deletions = append(deletions, func() {
|
||||||
|
astutil.DeleteNamedImport(fset, file, explicit, path)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the deletions.
|
||||||
|
for _, del := range deletions {
|
||||||
|
del()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// plural returns "n nouns", selecting the plural form as approriate.
|
||||||
|
func plural(n int, singular, plural string) string {
|
||||||
|
if n == 1 {
|
||||||
|
return "1 " + singular
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%d %s", n, plural)
|
||||||
|
}
|
||||||
|
}
|
||||||
161
src/cmd/vendor/golang.org/x/tools/internal/analysis/driverutil/print.go
generated
vendored
Normal file
161
src/cmd/vendor/golang.org/x/tools/internal/analysis/driverutil/print.go
generated
vendored
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
// Copyright 2025 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 driverutil
|
||||||
|
|
||||||
|
// This file defined output helpers common to all drivers.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"go/token"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(adonovan): don't accept an io.Writer if we don't report errors.
|
||||||
|
// Either accept a bytes.Buffer (infallible), or return a []byte.
|
||||||
|
|
||||||
|
// PrintPlain prints a diagnostic in plain text form.
|
||||||
|
// If contextLines is nonnegative, it also prints the
|
||||||
|
// offending line plus this many lines of context.
|
||||||
|
func PrintPlain(out io.Writer, fset *token.FileSet, contextLines int, diag analysis.Diagnostic) {
|
||||||
|
print := func(pos, end token.Pos, message string) {
|
||||||
|
posn := fset.Position(pos)
|
||||||
|
fmt.Fprintf(out, "%s: %s\n", posn, message)
|
||||||
|
|
||||||
|
// show offending line plus N lines of context.
|
||||||
|
if contextLines >= 0 {
|
||||||
|
end := fset.Position(end)
|
||||||
|
if !end.IsValid() {
|
||||||
|
end = posn
|
||||||
|
}
|
||||||
|
// TODO(adonovan): highlight the portion of the line indicated
|
||||||
|
// by pos...end using ASCII art, terminal colors, etc?
|
||||||
|
data, _ := os.ReadFile(posn.Filename)
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
for i := posn.Line - contextLines; i <= end.Line+contextLines; i++ {
|
||||||
|
if 1 <= i && i <= len(lines) {
|
||||||
|
fmt.Fprintf(out, "%d\t%s\n", i, lines[i-1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print(diag.Pos, diag.End, diag.Message)
|
||||||
|
for _, rel := range diag.Related {
|
||||||
|
print(rel.Pos, rel.End, "\t"+rel.Message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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]any
|
||||||
|
|
||||||
|
// A TextEdit describes the replacement of a portion of a file.
|
||||||
|
// Start and End are zero-based half-open indices into the original byte
|
||||||
|
// sequence of the file, and New is the new text.
|
||||||
|
type JSONTextEdit struct {
|
||||||
|
Filename string `json:"filename"`
|
||||||
|
Start int `json:"start"`
|
||||||
|
End int `json:"end"`
|
||||||
|
New string `json:"new"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// A JSONSuggestedFix describes an edit that should be applied as a whole or not
|
||||||
|
// at all. It might contain multiple TextEdits/text_edits if the SuggestedFix
|
||||||
|
// consists of multiple non-contiguous edits.
|
||||||
|
type JSONSuggestedFix struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Edits []JSONTextEdit `json:"edits"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// A JSONDiagnostic describes the JSON schema of an analysis.Diagnostic.
|
||||||
|
//
|
||||||
|
// TODO(matloob): include End position if present.
|
||||||
|
type JSONDiagnostic struct {
|
||||||
|
Category string `json:"category,omitempty"`
|
||||||
|
Posn string `json:"posn"` // e.g. "file.go:line:column"
|
||||||
|
Message string `json:"message"`
|
||||||
|
SuggestedFixes []JSONSuggestedFix `json:"suggested_fixes,omitempty"`
|
||||||
|
Related []JSONRelatedInformation `json:"related,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// A JSONRelated describes a secondary position and message related to
|
||||||
|
// a primary diagnostic.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): include End position if present.
|
||||||
|
type JSONRelatedInformation struct {
|
||||||
|
Posn string `json:"posn"` // e.g. "file.go:line:column"
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 any
|
||||||
|
if err != nil {
|
||||||
|
type jsonError struct {
|
||||||
|
Err string `json:"error"`
|
||||||
|
}
|
||||||
|
v = jsonError{err.Error()}
|
||||||
|
} else if len(diags) > 0 {
|
||||||
|
diagnostics := make([]JSONDiagnostic, 0, len(diags))
|
||||||
|
for _, f := range diags {
|
||||||
|
var fixes []JSONSuggestedFix
|
||||||
|
for _, fix := range f.SuggestedFixes {
|
||||||
|
var edits []JSONTextEdit
|
||||||
|
for _, edit := range fix.TextEdits {
|
||||||
|
edits = append(edits, JSONTextEdit{
|
||||||
|
Filename: fset.Position(edit.Pos).Filename,
|
||||||
|
Start: fset.Position(edit.Pos).Offset,
|
||||||
|
End: fset.Position(edit.End).Offset,
|
||||||
|
New: string(edit.NewText),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fixes = append(fixes, JSONSuggestedFix{
|
||||||
|
Message: fix.Message,
|
||||||
|
Edits: edits,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
var related []JSONRelatedInformation
|
||||||
|
for _, r := range f.Related {
|
||||||
|
related = append(related, JSONRelatedInformation{
|
||||||
|
Posn: fset.Position(r.Pos).String(),
|
||||||
|
Message: r.Message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
jdiag := JSONDiagnostic{
|
||||||
|
Category: f.Category,
|
||||||
|
Posn: fset.Position(f.Pos).String(),
|
||||||
|
Message: f.Message,
|
||||||
|
SuggestedFixes: fixes,
|
||||||
|
Related: related,
|
||||||
|
}
|
||||||
|
diagnostics = append(diagnostics, jdiag)
|
||||||
|
}
|
||||||
|
v = diagnostics
|
||||||
|
}
|
||||||
|
if v != nil {
|
||||||
|
m, ok := tree[id]
|
||||||
|
if !ok {
|
||||||
|
m = make(map[string]any)
|
||||||
|
tree[id] = m
|
||||||
|
}
|
||||||
|
m[name] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tree JSONTree) Print(out io.Writer) error {
|
||||||
|
data, err := json.MarshalIndent(tree, "", "\t")
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("internal error: JSON marshaling failed: %v", err)
|
||||||
|
}
|
||||||
|
_, err = fmt.Fprintf(out, "%s\n", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
43
src/cmd/vendor/golang.org/x/tools/internal/analysis/driverutil/readfile.go
generated
vendored
Normal file
43
src/cmd/vendor/golang.org/x/tools/internal/analysis/driverutil/readfile.go
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright 2020 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 driverutil
|
||||||
|
|
||||||
|
// This file defines helpers for implementing [analysis.Pass.ReadFile].
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A ReadFileFunc is a function that returns the
|
||||||
|
// contents of a file, such as [os.ReadFile].
|
||||||
|
type ReadFileFunc = func(filename string) ([]byte, error)
|
||||||
|
|
||||||
|
// CheckedReadFile returns a wrapper around a Pass.ReadFile
|
||||||
|
// function that performs the appropriate checks.
|
||||||
|
func CheckedReadFile(pass *analysis.Pass, readFile ReadFileFunc) ReadFileFunc {
|
||||||
|
return func(filename string) ([]byte, error) {
|
||||||
|
if err := CheckReadable(pass, filename); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return readFile(filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckReadable enforces the access policy defined by the ReadFile field of [analysis.Pass].
|
||||||
|
func CheckReadable(pass *analysis.Pass, filename string) error {
|
||||||
|
if slices.Contains(pass.OtherFiles, filename) ||
|
||||||
|
slices.Contains(pass.IgnoredFiles, filename) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, f := range pass.Files {
|
||||||
|
if pass.Fset.File(f.FileStart).Name() == filename {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Pass.ReadFile: %s is not among OtherFiles, IgnoredFiles, or names of Files", filename)
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue