mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd: update to x/tools@7d9453cc
go get golang.org/x/tools@master go mod tidy go mod vendor in both cmd and src, for (enforced) consistency. Also: GOWORK=off go generate -run=bundle std This will enable use of modernize and inline. Change-Id: I6348dd97ec2c41437b3ca899ed91f10815f2fe26 Reviewed-on: https://go-review.googlesource.com/c/go/+/707135 Reviewed-by: Michael Matloob <matloob@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Alan Donovan <adonovan@google.com> Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
parent
45eee553e2
commit
6cbe0920c4
70 changed files with 1600 additions and 1070 deletions
|
|
@ -6,16 +6,16 @@ require (
|
||||||
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5
|
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5
|
||||||
golang.org/x/arch v0.20.1-0.20250808194827-46ba08e3ae58
|
golang.org/x/arch v0.20.1-0.20250808194827-46ba08e3ae58
|
||||||
golang.org/x/build v0.0.0-20250806225920-b7c66c047964
|
golang.org/x/build v0.0.0-20250806225920-b7c66c047964
|
||||||
golang.org/x/mod v0.28.0
|
golang.org/x/mod v0.29.0
|
||||||
golang.org/x/sync v0.17.0
|
golang.org/x/sync v0.17.0
|
||||||
golang.org/x/sys v0.36.0
|
golang.org/x/sys v0.37.0
|
||||||
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053
|
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8
|
||||||
golang.org/x/term v0.34.0
|
golang.org/x/term v0.34.0
|
||||||
golang.org/x/tools v0.37.1-0.20250924232827-4df13e317ce4
|
golang.org/x/tools v0.38.1-0.20251015192825-7d9453ccc0f5
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b // indirect
|
github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b // indirect
|
||||||
golang.org/x/text v0.29.0 // indirect
|
golang.org/x/text v0.30.0 // indirect
|
||||||
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef // indirect
|
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -10,19 +10,19 @@ golang.org/x/arch v0.20.1-0.20250808194827-46ba08e3ae58 h1:uxPa6+/WsUfzikIAPMqpT
|
||||||
golang.org/x/arch v0.20.1-0.20250808194827-46ba08e3ae58/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
golang.org/x/arch v0.20.1-0.20250808194827-46ba08e3ae58/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||||
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.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||||
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8=
|
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU=
|
||||||
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE=
|
golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
|
||||||
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.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||||
golang.org/x/tools v0.37.1-0.20250924232827-4df13e317ce4 h1:IcXDtHggZZo+GzNzvVRPyNFLnOc2/Z1gg3ZVIWF2uCU=
|
golang.org/x/tools v0.38.1-0.20251015192825-7d9453ccc0f5 h1:cz7f45KGWAtyIrz6bm45Gc+lw8beIxBSW3EQh4Bwbg4=
|
||||||
golang.org/x/tools v0.37.1-0.20250924232827-4df13e317ce4/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
golang.org/x/tools v0.38.1-0.20251015192825-7d9453ccc0f5/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||||
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=
|
||||||
|
|
|
||||||
9
src/cmd/vendor/golang.org/x/sys/unix/affinity_linux.go
generated
vendored
9
src/cmd/vendor/golang.org/x/sys/unix/affinity_linux.go
generated
vendored
|
|
@ -41,6 +41,15 @@ func (s *CPUSet) Zero() {
|
||||||
clear(s[:])
|
clear(s[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill adds all possible CPU bits to the set s. On Linux, [SchedSetaffinity]
|
||||||
|
// will silently ignore any invalid CPU bits in [CPUSet] so this is an
|
||||||
|
// efficient way of resetting the CPU affinity of a process.
|
||||||
|
func (s *CPUSet) Fill() {
|
||||||
|
for i := range s {
|
||||||
|
s[i] = ^cpuMask(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func cpuBitsIndex(cpu int) int {
|
func cpuBitsIndex(cpu int) int {
|
||||||
return cpu / _NCPUBITS
|
return cpu / _NCPUBITS
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/sys/unix/fdset.go
generated
vendored
4
src/cmd/vendor/golang.org/x/sys/unix/fdset.go
generated
vendored
|
|
@ -23,7 +23,5 @@ func (fds *FdSet) IsSet(fd int) bool {
|
||||||
|
|
||||||
// Zero clears the set fds.
|
// Zero clears the set fds.
|
||||||
func (fds *FdSet) Zero() {
|
func (fds *FdSet) Zero() {
|
||||||
for i := range fds.Bits {
|
clear(fds.Bits[:])
|
||||||
fds.Bits[i] = 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go
generated
vendored
4
src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go
generated
vendored
|
|
@ -111,9 +111,7 @@ func (ifr *Ifreq) SetUint32(v uint32) {
|
||||||
// clear zeroes the ifreq's union field to prevent trailing garbage data from
|
// clear zeroes the ifreq's union field to prevent trailing garbage data from
|
||||||
// being sent to the kernel if an ifreq is reused.
|
// being sent to the kernel if an ifreq is reused.
|
||||||
func (ifr *Ifreq) clear() {
|
func (ifr *Ifreq) clear() {
|
||||||
for i := range ifr.raw.Ifru {
|
clear(ifr.raw.Ifru[:])
|
||||||
ifr.raw.Ifru[i] = 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mdlayher): export as IfreqData? For now we can provide helpers such as
|
// TODO(mdlayher): export as IfreqData? For now we can provide helpers such as
|
||||||
|
|
|
||||||
1
src/cmd/vendor/golang.org/x/sys/unix/mkall.sh
generated
vendored
1
src/cmd/vendor/golang.org/x/sys/unix/mkall.sh
generated
vendored
|
|
@ -49,6 +49,7 @@ esac
|
||||||
if [[ "$GOOS" = "linux" ]]; then
|
if [[ "$GOOS" = "linux" ]]; then
|
||||||
# Use the Docker-based build system
|
# Use the Docker-based build system
|
||||||
# Files generated through docker (use $cmd so you can Ctl-C the build or run)
|
# Files generated through docker (use $cmd so you can Ctl-C the build or run)
|
||||||
|
set -e
|
||||||
$cmd docker build --tag generate:$GOOS $GOOS
|
$cmd docker build --tag generate:$GOOS $GOOS
|
||||||
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && pwd):/build generate:$GOOS
|
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && pwd):/build generate:$GOOS
|
||||||
exit
|
exit
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
4
src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go
generated
vendored
|
|
@ -801,9 +801,7 @@ func (sa *SockaddrPPPoE) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||||
// one. The kernel expects SID to be in network byte order.
|
// one. The kernel expects SID to be in network byte order.
|
||||||
binary.BigEndian.PutUint16(sa.raw[6:8], sa.SID)
|
binary.BigEndian.PutUint16(sa.raw[6:8], sa.SID)
|
||||||
copy(sa.raw[8:14], sa.Remote)
|
copy(sa.raw[8:14], sa.Remote)
|
||||||
for i := 14; i < 14+IFNAMSIZ; i++ {
|
clear(sa.raw[14 : 14+IFNAMSIZ])
|
||||||
sa.raw[i] = 0
|
|
||||||
}
|
|
||||||
copy(sa.raw[14:], sa.Dev)
|
copy(sa.raw[14:], sa.Dev)
|
||||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrPPPoX, nil
|
return unsafe.Pointer(&sa.raw), SizeofSockaddrPPPoX, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
src/cmd/vendor/golang.org/x/sys/unix/syscall_netbsd.go
generated
vendored
17
src/cmd/vendor/golang.org/x/sys/unix/syscall_netbsd.go
generated
vendored
|
|
@ -248,6 +248,23 @@ func Statvfs(path string, buf *Statvfs_t) (err error) {
|
||||||
return Statvfs1(path, buf, ST_WAIT)
|
return Statvfs1(path, buf, ST_WAIT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Getvfsstat(buf []Statvfs_t, flags int) (n int, err error) {
|
||||||
|
var (
|
||||||
|
_p0 unsafe.Pointer
|
||||||
|
bufsize uintptr
|
||||||
|
)
|
||||||
|
if len(buf) > 0 {
|
||||||
|
_p0 = unsafe.Pointer(&buf[0])
|
||||||
|
bufsize = unsafe.Sizeof(Statvfs_t{}) * uintptr(len(buf))
|
||||||
|
}
|
||||||
|
r0, _, e1 := Syscall(SYS_GETVFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
|
||||||
|
n = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exposed directly
|
* Exposed directly
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
2
src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
2
src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go
generated
vendored
|
|
@ -321,6 +321,8 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||||
//sys SetConsoleOutputCP(cp uint32) (err error) = kernel32.SetConsoleOutputCP
|
//sys SetConsoleOutputCP(cp uint32) (err error) = kernel32.SetConsoleOutputCP
|
||||||
//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
|
//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
|
||||||
//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
|
//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
|
||||||
|
//sys GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) = kernel32.GetNumberOfConsoleInputEvents
|
||||||
|
//sys FlushConsoleInputBuffer(console Handle) (err error) = kernel32.FlushConsoleInputBuffer
|
||||||
//sys resizePseudoConsole(pconsole Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole
|
//sys resizePseudoConsole(pconsole Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole
|
||||||
//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
|
//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
|
||||||
//sys Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW
|
//sys Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW
|
||||||
|
|
|
||||||
16
src/cmd/vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
16
src/cmd/vendor/golang.org/x/sys/windows/types_windows.go
generated
vendored
|
|
@ -65,6 +65,22 @@ var signals = [...]string{
|
||||||
15: "terminated",
|
15: "terminated",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File flags for [os.OpenFile]. The O_ prefix is used to indicate
|
||||||
|
// that these flags are specific to the OpenFile function.
|
||||||
|
const (
|
||||||
|
O_FILE_FLAG_OPEN_NO_RECALL = FILE_FLAG_OPEN_NO_RECALL
|
||||||
|
O_FILE_FLAG_OPEN_REPARSE_POINT = FILE_FLAG_OPEN_REPARSE_POINT
|
||||||
|
O_FILE_FLAG_SESSION_AWARE = FILE_FLAG_SESSION_AWARE
|
||||||
|
O_FILE_FLAG_POSIX_SEMANTICS = FILE_FLAG_POSIX_SEMANTICS
|
||||||
|
O_FILE_FLAG_BACKUP_SEMANTICS = FILE_FLAG_BACKUP_SEMANTICS
|
||||||
|
O_FILE_FLAG_DELETE_ON_CLOSE = FILE_FLAG_DELETE_ON_CLOSE
|
||||||
|
O_FILE_FLAG_SEQUENTIAL_SCAN = FILE_FLAG_SEQUENTIAL_SCAN
|
||||||
|
O_FILE_FLAG_RANDOM_ACCESS = FILE_FLAG_RANDOM_ACCESS
|
||||||
|
O_FILE_FLAG_NO_BUFFERING = FILE_FLAG_NO_BUFFERING
|
||||||
|
O_FILE_FLAG_OVERLAPPED = FILE_FLAG_OVERLAPPED
|
||||||
|
O_FILE_FLAG_WRITE_THROUGH = FILE_FLAG_WRITE_THROUGH
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FILE_READ_DATA = 0x00000001
|
FILE_READ_DATA = 0x00000001
|
||||||
FILE_READ_ATTRIBUTES = 0x00000080
|
FILE_READ_ATTRIBUTES = 0x00000080
|
||||||
|
|
|
||||||
18
src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
generated
vendored
18
src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go
generated
vendored
|
|
@ -238,6 +238,7 @@ var (
|
||||||
procFindResourceW = modkernel32.NewProc("FindResourceW")
|
procFindResourceW = modkernel32.NewProc("FindResourceW")
|
||||||
procFindVolumeClose = modkernel32.NewProc("FindVolumeClose")
|
procFindVolumeClose = modkernel32.NewProc("FindVolumeClose")
|
||||||
procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose")
|
procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose")
|
||||||
|
procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer")
|
||||||
procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers")
|
procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers")
|
||||||
procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile")
|
procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile")
|
||||||
procFormatMessageW = modkernel32.NewProc("FormatMessageW")
|
procFormatMessageW = modkernel32.NewProc("FormatMessageW")
|
||||||
|
|
@ -284,6 +285,7 @@ var (
|
||||||
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
|
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
|
||||||
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
|
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
|
||||||
procGetNamedPipeServerProcessId = modkernel32.NewProc("GetNamedPipeServerProcessId")
|
procGetNamedPipeServerProcessId = modkernel32.NewProc("GetNamedPipeServerProcessId")
|
||||||
|
procGetNumberOfConsoleInputEvents = modkernel32.NewProc("GetNumberOfConsoleInputEvents")
|
||||||
procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult")
|
procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult")
|
||||||
procGetPriorityClass = modkernel32.NewProc("GetPriorityClass")
|
procGetPriorityClass = modkernel32.NewProc("GetPriorityClass")
|
||||||
procGetProcAddress = modkernel32.NewProc("GetProcAddress")
|
procGetProcAddress = modkernel32.NewProc("GetProcAddress")
|
||||||
|
|
@ -2111,6 +2113,14 @@ func FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FlushConsoleInputBuffer(console Handle) (err error) {
|
||||||
|
r1, _, e1 := syscall.SyscallN(procFlushConsoleInputBuffer.Addr(), uintptr(console))
|
||||||
|
if r1 == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func FlushFileBuffers(handle Handle) (err error) {
|
func FlushFileBuffers(handle Handle) (err error) {
|
||||||
r1, _, e1 := syscall.SyscallN(procFlushFileBuffers.Addr(), uintptr(handle))
|
r1, _, e1 := syscall.SyscallN(procFlushFileBuffers.Addr(), uintptr(handle))
|
||||||
if r1 == 0 {
|
if r1 == 0 {
|
||||||
|
|
@ -2481,6 +2491,14 @@ func GetNamedPipeServerProcessId(pipe Handle, serverProcessID *uint32) (err erro
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) {
|
||||||
|
r1, _, e1 := syscall.SyscallN(procGetNumberOfConsoleInputEvents.Addr(), uintptr(console), uintptr(unsafe.Pointer(numevents)))
|
||||||
|
if r1 == 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) {
|
func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) {
|
||||||
var _p0 uint32
|
var _p0 uint32
|
||||||
if wait {
|
if wait {
|
||||||
|
|
|
||||||
8
src/cmd/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go
generated
vendored
8
src/cmd/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go
generated
vendored
|
|
@ -326,11 +326,3 @@ func parseStackPCs(crash string) ([]uintptr, error) {
|
||||||
}
|
}
|
||||||
return pcs, nil
|
return pcs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func min(x, y int) int {
|
|
||||||
if x < y {
|
|
||||||
return x
|
|
||||||
} else {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
26
src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/help.go
generated
vendored
26
src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/help.go
generated
vendored
|
|
@ -17,10 +17,26 @@ import (
|
||||||
|
|
||||||
const help = `PROGNAME is a tool for static analysis of Go programs.
|
const help = `PROGNAME is a tool for static analysis of Go programs.
|
||||||
|
|
||||||
PROGNAME examines Go source code and reports suspicious constructs,
|
PROGNAME examines Go source code and reports diagnostics for
|
||||||
such as Printf calls whose arguments do not align with the format
|
suspicious constructs or opportunities for improvement.
|
||||||
string. It uses heuristics that do not guarantee all reports are
|
Diagnostics may include suggested fixes.
|
||||||
genuine problems, but it can find errors not caught by the compilers.
|
|
||||||
|
An example of a suspicious construct is a Printf call whose arguments
|
||||||
|
do not align with the format string. Analyzers may use heuristics that
|
||||||
|
do not guarantee all reports are genuine problems, but can find
|
||||||
|
mistakes not caught by the compiler.
|
||||||
|
|
||||||
|
An example of an opportunity for improvement is a loop over
|
||||||
|
strings.Split(doc, "\n"), which may be replaced by a loop over the
|
||||||
|
strings.SplitSeq iterator, avoiding an array allocation.
|
||||||
|
Diagnostics in such cases may report non-problems,
|
||||||
|
but should carry fixes that may be safely applied.
|
||||||
|
|
||||||
|
For analyzers of the first kind, use "go vet -vettool=PROGRAM"
|
||||||
|
to run the tool and report diagnostics.
|
||||||
|
|
||||||
|
For analyzers of the second kind, use "go fix -fixtool=PROGRAM"
|
||||||
|
to run the tool and apply the fixes it suggests.
|
||||||
`
|
`
|
||||||
|
|
||||||
// Help implements the help subcommand for a multichecker or unitchecker
|
// Help implements the help subcommand for a multichecker or unitchecker
|
||||||
|
|
@ -29,7 +45,7 @@ genuine problems, but it can find errors not caught by the compilers.
|
||||||
func Help(progname string, analyzers []*analysis.Analyzer, args []string) {
|
func Help(progname string, analyzers []*analysis.Analyzer, args []string) {
|
||||||
// No args: show summary of all analyzers.
|
// No args: show summary of all analyzers.
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
fmt.Println(strings.Replace(help, "PROGNAME", progname, -1))
|
fmt.Println(strings.ReplaceAll(help, "PROGNAME", progname))
|
||||||
fmt.Println("Registered analyzers:")
|
fmt.Println("Registered analyzers:")
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
sort.Slice(analyzers, func(i, j int) bool {
|
sort.Slice(analyzers, func(i, j int) bool {
|
||||||
|
|
|
||||||
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
|
|
@ -13,9 +13,9 @@ 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/analysisutil"
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
//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: analysisutil.MustExtractDoc(doc, "appends"),
|
Doc: analysisinternal.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,
|
||||||
|
|
|
||||||
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
generated
vendored
8
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/go/analysis/passes/internal/analysisutil"
|
"golang.org/x/tools/internal/analysisinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
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 := analysisutil.ReadFile(pass, fname)
|
content, tf, err := analysisinternal.ReadFile(pass, fname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -211,7 +211,7 @@ Files:
|
||||||
resultStr = "result register"
|
resultStr = "result register"
|
||||||
}
|
}
|
||||||
for _, line := range retLine {
|
for _, line := range retLine {
|
||||||
pass.Reportf(analysisutil.LineStart(tf, line), "[%s] %s: RET without writing to %s", arch, fnName, resultStr)
|
pass.Reportf(tf.LineStart(line), "[%s] %s: RET without writing to %s", arch, fnName, resultStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
retLine = nil
|
retLine = nil
|
||||||
|
|
@ -227,7 +227,7 @@ Files:
|
||||||
lineno++
|
lineno++
|
||||||
|
|
||||||
badf := func(format string, args ...any) {
|
badf := func(format string, args ...any) {
|
||||||
pass.Reportf(analysisutil.LineStart(tf, lineno), "[%s] %s: %s", arch, fnName, fmt.Sprintf(format, args...))
|
pass.Reportf(tf.LineStart(lineno), "[%s] %s: %s", arch, fnName, fmt.Sprintf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
if arch == "" {
|
if arch == "" {
|
||||||
|
|
|
||||||
39
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go
generated
vendored
39
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/assign/assign.go
generated
vendored
|
|
@ -17,9 +17,11 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
"golang.org/x/tools/internal/astutil"
|
||||||
|
"golang.org/x/tools/internal/refactor"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -27,26 +29,26 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "assign",
|
Name: "assign",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "assign"),
|
Doc: analysisinternal.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,
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
func run(pass *analysis.Pass) (any, error) {
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
var (
|
||||||
|
inspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||||
|
info = pass.TypesInfo
|
||||||
|
)
|
||||||
|
|
||||||
nodeFilter := []ast.Node{
|
for curAssign := range inspect.Root().Preorder((*ast.AssignStmt)(nil)) {
|
||||||
(*ast.AssignStmt)(nil),
|
stmt := curAssign.Node().(*ast.AssignStmt)
|
||||||
}
|
|
||||||
inspect.Preorder(nodeFilter, func(n ast.Node) {
|
|
||||||
stmt := n.(*ast.AssignStmt)
|
|
||||||
if stmt.Tok != token.ASSIGN {
|
if stmt.Tok != token.ASSIGN {
|
||||||
return // ignore :=
|
continue // ignore :=
|
||||||
}
|
}
|
||||||
if len(stmt.Lhs) != len(stmt.Rhs) {
|
if len(stmt.Lhs) != len(stmt.Rhs) {
|
||||||
// If LHS and RHS have different cardinality, they can't be the same.
|
// If LHS and RHS have different cardinality, they can't be the same.
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete redundant LHS, RHS pairs, taking care
|
// Delete redundant LHS, RHS pairs, taking care
|
||||||
|
|
@ -61,13 +63,13 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
isSelfAssign := false
|
isSelfAssign := false
|
||||||
var le string
|
var le string
|
||||||
|
|
||||||
if !analysisutil.HasSideEffects(pass.TypesInfo, lhs) &&
|
if typesinternal.NoEffects(info, lhs) &&
|
||||||
!analysisutil.HasSideEffects(pass.TypesInfo, rhs) &&
|
typesinternal.NoEffects(info, rhs) &&
|
||||||
!isMapIndex(pass.TypesInfo, lhs) &&
|
!isMapIndex(info, lhs) &&
|
||||||
reflect.TypeOf(lhs) == reflect.TypeOf(rhs) { // short-circuit the heavy-weight gofmt check
|
reflect.TypeOf(lhs) == reflect.TypeOf(rhs) { // short-circuit the heavy-weight gofmt check
|
||||||
|
|
||||||
le = analysisinternal.Format(pass.Fset, lhs)
|
le = astutil.Format(pass.Fset, lhs)
|
||||||
re := analysisinternal.Format(pass.Fset, rhs)
|
re := astutil.Format(pass.Fset, rhs)
|
||||||
if le == re {
|
if le == re {
|
||||||
isSelfAssign = true
|
isSelfAssign = true
|
||||||
}
|
}
|
||||||
|
|
@ -109,13 +111,14 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(exprs) == 0 {
|
if len(exprs) == 0 {
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(exprs) == len(stmt.Lhs) {
|
if len(exprs) == len(stmt.Lhs) {
|
||||||
// If every part of the statement is a self-assignment,
|
// If every part of the statement is a self-assignment,
|
||||||
// remove the whole statement.
|
// remove the whole statement.
|
||||||
edits = []analysis.TextEdit{{Pos: stmt.Pos(), End: stmt.End()}}
|
tokFile := pass.Fset.File(stmt.Pos())
|
||||||
|
edits = refactor.DeleteStmt(tokFile, curAssign)
|
||||||
}
|
}
|
||||||
|
|
||||||
pass.Report(analysis.Diagnostic{
|
pass.Report(analysis.Diagnostic{
|
||||||
|
|
@ -126,7 +129,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
TextEdits: edits,
|
TextEdits: edits,
|
||||||
}},
|
}},
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/atomic/atomic.go
generated
vendored
11
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/atomic/atomic.go
generated
vendored
|
|
@ -11,10 +11,11 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
"golang.org/x/tools/internal/astutil"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -22,7 +23,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "atomic",
|
Name: "atomic",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "atomic"),
|
Doc: analysisinternal.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,
|
||||||
|
|
@ -30,7 +31,7 @@ var Analyzer = &analysis.Analyzer{
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
func run(pass *analysis.Pass) (any, error) {
|
||||||
if !analysisinternal.Imports(pass.Pkg, "sync/atomic") {
|
if !typesinternal.Imports(pass.Pkg, "sync/atomic") {
|
||||||
return nil, nil // doesn't directly import sync/atomic
|
return nil, nil // doesn't directly import sync/atomic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,7 +55,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
obj := typeutil.Callee(pass.TypesInfo, call)
|
obj := typeutil.Callee(pass.TypesInfo, call)
|
||||||
if analysisinternal.IsFunctionNamed(obj, "sync/atomic", "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr") {
|
if typesinternal.IsFunctionNamed(obj, "sync/atomic", "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr") {
|
||||||
checkAtomicAddAssignment(pass, n.Lhs[i], call)
|
checkAtomicAddAssignment(pass, n.Lhs[i], call)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +73,7 @@ func checkAtomicAddAssignment(pass *analysis.Pass, left ast.Expr, call *ast.Call
|
||||||
arg := call.Args[0]
|
arg := call.Args[0]
|
||||||
broken := false
|
broken := false
|
||||||
|
|
||||||
gofmt := func(e ast.Expr) string { return analysisinternal.Format(pass.Fset, e) }
|
gofmt := func(e ast.Expr) string { return astutil.Format(pass.Fset, e) }
|
||||||
|
|
||||||
if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND {
|
if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND {
|
||||||
broken = gofmt(left) == gofmt(uarg.X)
|
broken = gofmt(left) == gofmt(uarg.X)
|
||||||
|
|
|
||||||
12
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/bools/bools.go
generated
vendored
12
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/bools/bools.go
generated
vendored
|
|
@ -13,9 +13,9 @@ 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/analysisutil"
|
|
||||||
"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/astutil"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
const Doc = "check for common mistakes involving boolean operators"
|
const Doc = "check for common mistakes involving boolean operators"
|
||||||
|
|
@ -84,7 +84,7 @@ func (op boolOp) commutativeSets(info *types.Info, e *ast.BinaryExpr, seen map[*
|
||||||
i := 0
|
i := 0
|
||||||
var sets [][]ast.Expr
|
var sets [][]ast.Expr
|
||||||
for j := 0; j <= len(exprs); j++ {
|
for j := 0; j <= len(exprs); j++ {
|
||||||
if j == len(exprs) || analysisutil.HasSideEffects(info, exprs[j]) {
|
if j == len(exprs) || !typesinternal.NoEffects(info, exprs[j]) {
|
||||||
if i < j {
|
if i < j {
|
||||||
sets = append(sets, exprs[i:j])
|
sets = append(sets, exprs[i:j])
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +104,7 @@ func (op boolOp) commutativeSets(info *types.Info, e *ast.BinaryExpr, seen map[*
|
||||||
func (op boolOp) checkRedundant(pass *analysis.Pass, exprs []ast.Expr) {
|
func (op boolOp) checkRedundant(pass *analysis.Pass, exprs []ast.Expr) {
|
||||||
seen := make(map[string]bool)
|
seen := make(map[string]bool)
|
||||||
for _, e := range exprs {
|
for _, e := range exprs {
|
||||||
efmt := analysisinternal.Format(pass.Fset, e)
|
efmt := astutil.Format(pass.Fset, e)
|
||||||
if seen[efmt] {
|
if seen[efmt] {
|
||||||
pass.ReportRangef(e, "redundant %s: %s %s %s", op.name, efmt, op.tok, efmt)
|
pass.ReportRangef(e, "redundant %s: %s %s %s", op.name, efmt, op.tok, efmt)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -150,8 +150,8 @@ func (op boolOp) checkSuspect(pass *analysis.Pass, exprs []ast.Expr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// e is of the form 'x != c' or 'x == c'.
|
// e is of the form 'x != c' or 'x == c'.
|
||||||
xfmt := analysisinternal.Format(pass.Fset, x)
|
xfmt := astutil.Format(pass.Fset, x)
|
||||||
efmt := analysisinternal.Format(pass.Fset, e)
|
efmt := astutil.Format(pass.Fset, e)
|
||||||
if prev, found := seen[xfmt]; found {
|
if prev, found := seen[xfmt]; found {
|
||||||
// checkRedundant handles the case in which efmt == prev.
|
// checkRedundant handles the case in which efmt == prev.
|
||||||
if efmt != prev {
|
if efmt != prev {
|
||||||
|
|
|
||||||
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/go/analysis/passes/internal/analysisutil"
|
"golang.org/x/tools/internal/analysisinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
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 := analysisutil.ReadFile(pass, filename)
|
content, tf, err := analysisinternal.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
|
|
@ -18,7 +18,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
const debug = false
|
const debug = false
|
||||||
|
|
@ -41,7 +41,7 @@ var Analyzer = &analysis.Analyzer{
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
func run(pass *analysis.Pass) (any, error) {
|
||||||
if !analysisinternal.Imports(pass.Pkg, "runtime/cgo") {
|
if !typesinternal.Imports(pass.Pkg, "runtime/cgo") {
|
||||||
return nil, nil // doesn't use cgo
|
return nil, nil // doesn't use cgo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
15
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go
generated
vendored
15
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/copylock/copylock.go
generated
vendored
|
|
@ -16,8 +16,9 @@ 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/astutil"
|
||||||
"golang.org/x/tools/internal/typeparams"
|
"golang.org/x/tools/internal/typeparams"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
"golang.org/x/tools/internal/versions"
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -86,7 +87,7 @@ func checkCopyLocksAssign(pass *analysis.Pass, assign *ast.AssignStmt, goversion
|
||||||
lhs := assign.Lhs
|
lhs := assign.Lhs
|
||||||
for i, x := range assign.Rhs {
|
for i, x := range assign.Rhs {
|
||||||
if path := lockPathRhs(pass, x); path != nil {
|
if path := lockPathRhs(pass, x); path != nil {
|
||||||
pass.ReportRangef(x, "assignment copies lock value to %v: %v", analysisinternal.Format(pass.Fset, assign.Lhs[i]), path)
|
pass.ReportRangef(x, "assignment copies lock value to %v: %v", astutil.Format(pass.Fset, assign.Lhs[i]), path)
|
||||||
lhs = nil // An lhs has been reported. We prefer the assignment warning and do not report twice.
|
lhs = nil // An lhs has been reported. We prefer the assignment warning and do not report twice.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +101,7 @@ func checkCopyLocksAssign(pass *analysis.Pass, assign *ast.AssignStmt, goversion
|
||||||
if id, ok := l.(*ast.Ident); ok && id.Name != "_" {
|
if id, ok := l.(*ast.Ident); ok && id.Name != "_" {
|
||||||
if obj := pass.TypesInfo.Defs[id]; obj != nil && obj.Type() != nil {
|
if obj := pass.TypesInfo.Defs[id]; obj != nil && obj.Type() != nil {
|
||||||
if path := lockPath(pass.Pkg, obj.Type(), nil); path != nil {
|
if path := lockPath(pass.Pkg, obj.Type(), nil); path != nil {
|
||||||
pass.ReportRangef(l, "for loop iteration copies lock value to %v: %v", analysisinternal.Format(pass.Fset, l), path)
|
pass.ReportRangef(l, "for loop iteration copies lock value to %v: %v", astutil.Format(pass.Fset, l), path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +133,7 @@ func checkCopyLocksCompositeLit(pass *analysis.Pass, cl *ast.CompositeLit) {
|
||||||
x = node.Value
|
x = node.Value
|
||||||
}
|
}
|
||||||
if path := lockPathRhs(pass, x); path != nil {
|
if path := lockPathRhs(pass, x); path != nil {
|
||||||
pass.ReportRangef(x, "literal copies lock value from %v: %v", analysisinternal.Format(pass.Fset, x), path)
|
pass.ReportRangef(x, "literal copies lock value from %v: %v", astutil.Format(pass.Fset, x), path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +167,7 @@ func checkCopyLocksCallExpr(pass *analysis.Pass, ce *ast.CallExpr) {
|
||||||
}
|
}
|
||||||
for _, x := range ce.Args {
|
for _, x := range ce.Args {
|
||||||
if path := lockPathRhs(pass, x); path != nil {
|
if path := lockPathRhs(pass, x); path != nil {
|
||||||
pass.ReportRangef(x, "call of %s copies lock value: %v", analysisinternal.Format(pass.Fset, ce.Fun), path)
|
pass.ReportRangef(x, "call of %s copies lock value: %v", astutil.Format(pass.Fset, ce.Fun), path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -233,7 +234,7 @@ func checkCopyLocksRangeVar(pass *analysis.Pass, rtok token.Token, e ast.Expr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if path := lockPath(pass.Pkg, typ, nil); path != nil {
|
if path := lockPath(pass.Pkg, typ, nil); path != nil {
|
||||||
pass.Reportf(e.Pos(), "range var %s copies lock: %v", analysisinternal.Format(pass.Fset, e), path)
|
pass.Reportf(e.Pos(), "range var %s copies lock: %v", astutil.Format(pass.Fset, e), path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -353,7 +354,7 @@ func lockPath(tpkg *types.Package, typ types.Type, seen map[types.Type]bool) typ
|
||||||
// In go1.10, sync.noCopy did not implement Locker.
|
// In go1.10, sync.noCopy did not implement Locker.
|
||||||
// (The Unlock method was added only in CL 121876.)
|
// (The Unlock method was added only in CL 121876.)
|
||||||
// TODO(adonovan): remove workaround when we drop go1.10.
|
// TODO(adonovan): remove workaround when we drop go1.10.
|
||||||
if analysisinternal.IsTypeNamed(typ, "sync", "noCopy") {
|
if typesinternal.IsTypeNamed(typ, "sync", "noCopy") {
|
||||||
return []string{typ.String()}
|
return []string{typ.String()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/defers/defers.go
generated
vendored
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/defers/defers.go
generated
vendored
|
|
@ -10,10 +10,10 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -23,20 +23,20 @@ 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"),
|
||||||
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",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "defers"),
|
|
||||||
Run: run,
|
Run: run,
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
func run(pass *analysis.Pass) (any, error) {
|
||||||
if !analysisinternal.Imports(pass.Pkg, "time") {
|
if !typesinternal.Imports(pass.Pkg, "time") {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDeferCall := func(node ast.Node) bool {
|
checkDeferCall := func(node ast.Node) bool {
|
||||||
switch v := node.(type) {
|
switch v := node.(type) {
|
||||||
case *ast.CallExpr:
|
case *ast.CallExpr:
|
||||||
if analysisinternal.IsFunctionNamed(typeutil.Callee(pass.TypesInfo, v), "time", "Since") {
|
if typesinternal.IsFunctionNamed(typeutil.Callee(pass.TypesInfo, v), "time", "Since") {
|
||||||
pass.Reportf(v.Pos(), "call to time.Since is not deferred")
|
pass.Reportf(v.Pos(), "call to time.Since is not deferred")
|
||||||
}
|
}
|
||||||
case *ast.FuncLit:
|
case *ast.FuncLit:
|
||||||
|
|
|
||||||
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/go/analysis/passes/internal/analysisutil"
|
"golang.org/x/tools/internal/analysisinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
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 := analysisutil.ReadFile(pass, filename)
|
content, tf, err := analysisinternal.ReadFile(pass, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
63
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go
generated
vendored
63
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go
generated
vendored
|
|
@ -12,22 +12,20 @@ import (
|
||||||
"go/types"
|
"go/types"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
typeindexanalyzer "golang.org/x/tools/internal/analysisinternal/typeindex"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
"golang.org/x/tools/go/types/typeutil"
|
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const Doc = `report passing non-pointer or non-error values to errors.As
|
const Doc = `report passing non-pointer or non-error values to errors.As
|
||||||
|
|
||||||
The errorsas analysis reports calls to errors.As where the type
|
The errorsas analyzer reports calls to errors.As where the type
|
||||||
of the second argument is not a pointer to a type implementing error.`
|
of the second argument is not a pointer to a type implementing error.`
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "errorsas",
|
Name: "errorsas",
|
||||||
Doc: Doc,
|
Doc: Doc,
|
||||||
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/errorsas",
|
URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/errorsas",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{typeindexanalyzer.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,38 +37,31 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !analysisinternal.Imports(pass.Pkg, "errors") {
|
var (
|
||||||
return nil, nil // doesn't directly import errors
|
index = pass.ResultOf[typeindexanalyzer.Analyzer].(*typeindex.Index)
|
||||||
}
|
info = pass.TypesInfo
|
||||||
|
)
|
||||||
|
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
for curCall := range index.Calls(index.Object("errors", "As")) {
|
||||||
|
call := curCall.Node().(*ast.CallExpr)
|
||||||
nodeFilter := []ast.Node{
|
|
||||||
(*ast.CallExpr)(nil),
|
|
||||||
}
|
|
||||||
inspect.Preorder(nodeFilter, func(n ast.Node) {
|
|
||||||
call := n.(*ast.CallExpr)
|
|
||||||
obj := typeutil.Callee(pass.TypesInfo, call)
|
|
||||||
if !analysisinternal.IsFunctionNamed(obj, "errors", "As") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(call.Args) < 2 {
|
if len(call.Args) < 2 {
|
||||||
return // not enough arguments, e.g. called with return values of another function
|
continue // spread call: errors.As(pair())
|
||||||
}
|
}
|
||||||
if err := checkAsTarget(pass, call.Args[1]); err != nil {
|
|
||||||
|
// Check for incorrect arguments.
|
||||||
|
if err := checkAsTarget(info, call.Args[1]); err != nil {
|
||||||
pass.ReportRangef(call, "%v", err)
|
pass.ReportRangef(call, "%v", err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var errorType = types.Universe.Lookup("error").Type()
|
|
||||||
|
|
||||||
// checkAsTarget reports an error if the second argument to errors.As is invalid.
|
// checkAsTarget reports an error if the second argument to errors.As is invalid.
|
||||||
func checkAsTarget(pass *analysis.Pass, e ast.Expr) error {
|
func checkAsTarget(info *types.Info, e ast.Expr) error {
|
||||||
t := pass.TypesInfo.Types[e].Type
|
t := info.Types[e].Type
|
||||||
if it, ok := t.Underlying().(*types.Interface); ok && it.NumMethods() == 0 {
|
if types.Identical(t.Underlying(), anyType) {
|
||||||
// A target of interface{} is always allowed, since it often indicates
|
// A target of any is always allowed, since it often indicates
|
||||||
// a value forwarded from another source.
|
// a value forwarded from another source.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -78,12 +69,16 @@ func checkAsTarget(pass *analysis.Pass, e ast.Expr) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type")
|
return errors.New("second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type")
|
||||||
}
|
}
|
||||||
if pt.Elem() == errorType {
|
if types.Identical(pt.Elem(), errorType) {
|
||||||
return errors.New("second argument to errors.As should not be *error")
|
return errors.New("second argument to errors.As should not be *error")
|
||||||
}
|
}
|
||||||
_, ok = pt.Elem().Underlying().(*types.Interface)
|
if !types.IsInterface(pt.Elem()) && !types.AssignableTo(pt.Elem(), errorType) {
|
||||||
if ok || types.Implements(pt.Elem(), errorType.Underlying().(*types.Interface)) {
|
return errors.New("second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type")
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return errors.New("second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type")
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
anyType = types.Universe.Lookup("any").Type()
|
||||||
|
errorType = types.Universe.Lookup("error").Type()
|
||||||
|
)
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/framepointer/framepointer.go
generated
vendored
6
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/go/analysis/passes/internal/analysisutil"
|
"golang.org/x/tools/internal/analysisinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
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 := analysisutil.ReadFile(pass, fname)
|
content, tf, err := analysisinternal.ReadFile(pass, fname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -127,7 +127,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if arch.isFPWrite(line) {
|
if arch.isFPWrite(line) {
|
||||||
pass.Reportf(analysisutil.LineStart(tf, lineno), "frame pointer is clobbered before saving")
|
pass.Reportf(tf.LineStart(lineno), "frame pointer is clobbered before saving")
|
||||||
active = false
|
active = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/httpresponse/httpresponse.go
generated
vendored
9
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/httpresponse/httpresponse.go
generated
vendored
|
|
@ -13,7 +13,6 @@ 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/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -46,7 +45,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
|
|
||||||
// Fast path: if the package doesn't import net/http,
|
// Fast path: if the package doesn't import net/http,
|
||||||
// skip the traversal.
|
// skip the traversal.
|
||||||
if !analysisinternal.Imports(pass.Pkg, "net/http") {
|
if !typesinternal.Imports(pass.Pkg, "net/http") {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,7 +117,7 @@ func isHTTPFuncOrMethodOnClient(info *types.Info, expr *ast.CallExpr) bool {
|
||||||
return false // the function called does not return two values.
|
return false // the function called does not return two values.
|
||||||
}
|
}
|
||||||
isPtr, named := typesinternal.ReceiverNamed(res.At(0))
|
isPtr, named := typesinternal.ReceiverNamed(res.At(0))
|
||||||
if !isPtr || named == nil || !analysisinternal.IsTypeNamed(named, "net/http", "Response") {
|
if !isPtr || named == nil || !typesinternal.IsTypeNamed(named, "net/http", "Response") {
|
||||||
return false // the first return type is not *http.Response.
|
return false // the first return type is not *http.Response.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,11 +132,11 @@ func isHTTPFuncOrMethodOnClient(info *types.Info, expr *ast.CallExpr) bool {
|
||||||
return ok && id.Name == "http" // function in net/http package.
|
return ok && id.Name == "http" // function in net/http package.
|
||||||
}
|
}
|
||||||
|
|
||||||
if analysisinternal.IsTypeNamed(typ, "net/http", "Client") {
|
if typesinternal.IsTypeNamed(typ, "net/http", "Client") {
|
||||||
return true // method on http.Client.
|
return true // method on http.Client.
|
||||||
}
|
}
|
||||||
ptr, ok := types.Unalias(typ).(*types.Pointer)
|
ptr, ok := types.Unalias(typ).(*types.Pointer)
|
||||||
return ok && analysisinternal.IsTypeNamed(ptr.Elem(), "net/http", "Client") // method on *http.Client.
|
return ok && typesinternal.IsTypeNamed(ptr.Elem(), "net/http", "Client") // method on *http.Client.
|
||||||
}
|
}
|
||||||
|
|
||||||
// restOfBlock, given a traversal stack, finds the innermost containing
|
// restOfBlock, given a traversal stack, finds the innermost containing
|
||||||
|
|
|
||||||
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
|
|
@ -11,8 +11,8 @@ 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/analysisutil"
|
|
||||||
"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/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: analysisutil.MustExtractDoc(doc, "ifaceassert"),
|
Doc: analysisinternal.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,
|
||||||
|
|
|
||||||
99
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go
generated
vendored
99
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go
generated
vendored
|
|
@ -1,99 +0,0 @@
|
||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package analysisutil defines various helper functions
|
|
||||||
// used by two or more packages beneath go/analysis.
|
|
||||||
package analysisutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/ast"
|
|
||||||
"go/token"
|
|
||||||
"go/types"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HasSideEffects reports whether evaluation of e has side effects.
|
|
||||||
func HasSideEffects(info *types.Info, e ast.Expr) bool {
|
|
||||||
safe := true
|
|
||||||
ast.Inspect(e, func(node ast.Node) bool {
|
|
||||||
switch n := node.(type) {
|
|
||||||
case *ast.CallExpr:
|
|
||||||
typVal := info.Types[n.Fun]
|
|
||||||
switch {
|
|
||||||
case typVal.IsType():
|
|
||||||
// Type conversion, which is safe.
|
|
||||||
case typVal.IsBuiltin():
|
|
||||||
// Builtin func, conservatively assumed to not
|
|
||||||
// be safe for now.
|
|
||||||
safe = false
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
// A non-builtin func or method call.
|
|
||||||
// Conservatively assume that all of them have
|
|
||||||
// side effects for now.
|
|
||||||
safe = false
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
case *ast.UnaryExpr:
|
|
||||||
if n.Op == token.ARROW {
|
|
||||||
safe = false
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
return !safe
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadFile reads a file and adds it to the FileSet
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// LineStart returns the position of the start of the specified line
|
|
||||||
// within file f, or NoPos if there is no line of that number.
|
|
||||||
func LineStart(f *token.File, line int) token.Pos {
|
|
||||||
// Use binary search to find the start offset of this line.
|
|
||||||
//
|
|
||||||
// TODO(adonovan): eventually replace this function with the
|
|
||||||
// simpler and more efficient (*go/token.File).LineStart, added
|
|
||||||
// in go1.12.
|
|
||||||
|
|
||||||
min := 0 // inclusive
|
|
||||||
max := f.Size() // exclusive
|
|
||||||
for {
|
|
||||||
offset := (min + max) / 2
|
|
||||||
pos := f.Pos(offset)
|
|
||||||
posn := f.Position(pos)
|
|
||||||
if posn.Line == line {
|
|
||||||
return pos - (token.Pos(posn.Column) - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if min+1 >= max {
|
|
||||||
return token.NoPos
|
|
||||||
}
|
|
||||||
|
|
||||||
if posn.Line < line {
|
|
||||||
min = offset
|
|
||||||
} else {
|
|
||||||
max = offset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var MustExtractDoc = analysisinternal.MustExtractDoc
|
|
||||||
5
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go
generated
vendored
5
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/loopclosure/loopclosure.go
generated
vendored
|
|
@ -11,7 +11,6 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
|
@ -24,7 +23,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "loopclosure",
|
Name: "loopclosure",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "loopclosure"),
|
Doc: analysisinternal.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,
|
||||||
|
|
@ -369,5 +368,5 @@ func isMethodCall(info *types.Info, expr ast.Expr, pkgPath, typeName, method str
|
||||||
// Check that the receiver is a <pkgPath>.<typeName> or
|
// Check that the receiver is a <pkgPath>.<typeName> or
|
||||||
// *<pkgPath>.<typeName>.
|
// *<pkgPath>.<typeName>.
|
||||||
_, named := typesinternal.ReceiverNamed(recv)
|
_, named := typesinternal.ReceiverNamed(recv)
|
||||||
return analysisinternal.IsTypeNamed(named, pkgPath, typeName)
|
return typesinternal.IsTypeNamed(named, pkgPath, typeName)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/lostcancel/lostcancel.go
generated
vendored
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/lostcancel/lostcancel.go
generated
vendored
|
|
@ -13,11 +13,11 @@ import (
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/ctrlflow"
|
"golang.org/x/tools/go/analysis/passes/ctrlflow"
|
||||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||||
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
"golang.org/x/tools/internal/astutil"
|
"golang.org/x/tools/internal/astutil"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -25,7 +25,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "lostcancel",
|
Name: "lostcancel",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "lostcancel"),
|
Doc: analysisinternal.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{
|
||||||
|
|
@ -50,7 +50,7 @@ var contextPackage = "context"
|
||||||
// checkLostCancel analyzes a single named or literal function.
|
// checkLostCancel analyzes a single named or literal function.
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
func run(pass *analysis.Pass) (any, error) {
|
||||||
// Fast path: bypass check if file doesn't use context.WithCancel.
|
// Fast path: bypass check if file doesn't use context.WithCancel.
|
||||||
if !analysisinternal.Imports(pass.Pkg, contextPackage) {
|
if !typesinternal.Imports(pass.Pkg, contextPackage) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
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
|
|
@ -14,8 +14,8 @@ 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/analysisutil"
|
|
||||||
"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/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: analysisutil.MustExtractDoc(doc, "nilfunc"),
|
Doc: analysisinternal.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,
|
||||||
|
|
|
||||||
10
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/doc.go
generated
vendored
10
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/doc.go
generated
vendored
|
|
@ -82,6 +82,16 @@
|
||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
// A local function may also be inferred as a printf wrapper. If it
|
||||||
|
// is assigned to a variable, each call made through that variable will
|
||||||
|
// be checked just like a call to a function:
|
||||||
|
//
|
||||||
|
// logf := func(format string, args ...any) {
|
||||||
|
// message := fmt.Sprintf(format, args...)
|
||||||
|
// log.Printf("%s: %s", prefix, message)
|
||||||
|
// }
|
||||||
|
// logf("%s", 123) // logf format %s has arg 123 of wrong type int
|
||||||
|
//
|
||||||
// # Specifying printf wrappers by flag
|
// # Specifying printf wrappers by flag
|
||||||
//
|
//
|
||||||
// The -funcs flag specifies a comma-separated list of names of
|
// The -funcs flag specifies a comma-separated list of names of
|
||||||
|
|
|
||||||
415
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go
generated
vendored
415
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go
generated
vendored
|
|
@ -18,13 +18,14 @@ 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/analysisutil"
|
"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/analysisinternal"
|
||||||
"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"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
"golang.org/x/tools/internal/versions"
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -37,11 +38,11 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "printf",
|
Name: "printf",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "printf"),
|
Doc: analysisinternal.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,
|
||||||
ResultType: reflect.TypeOf((*Result)(nil)),
|
ResultType: reflect.TypeFor[*Result](),
|
||||||
FactTypes: []analysis.Fact{new(isWrapper)},
|
FactTypes: []analysis.Fact{new(isWrapper)},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,7 +71,7 @@ func (kind Kind) String() string {
|
||||||
// Result is the printf analyzer's result type. Clients may query the result
|
// Result is the printf analyzer's result type. Clients may query the result
|
||||||
// to learn whether a function behaves like fmt.Print or fmt.Printf.
|
// to learn whether a function behaves like fmt.Print or fmt.Printf.
|
||||||
type Result struct {
|
type Result struct {
|
||||||
funcs map[*types.Func]Kind
|
funcs map[types.Object]Kind
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kind reports whether fn behaves like fmt.Print or fmt.Printf.
|
// Kind reports whether fn behaves like fmt.Print or fmt.Printf.
|
||||||
|
|
@ -111,149 +112,210 @@ func (f *isWrapper) String() string {
|
||||||
|
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
func run(pass *analysis.Pass) (any, error) {
|
||||||
res := &Result{
|
res := &Result{
|
||||||
funcs: make(map[*types.Func]Kind),
|
funcs: make(map[types.Object]Kind),
|
||||||
}
|
}
|
||||||
findPrintfLike(pass, res)
|
findPrintLike(pass, res)
|
||||||
checkCalls(pass)
|
checkCalls(pass, res)
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type printfWrapper struct {
|
// A wrapper is a candidate print/printf wrapper function.
|
||||||
obj *types.Func
|
//
|
||||||
fdecl *ast.FuncDecl
|
// We represent functions generally as types.Object, not *Func, so
|
||||||
format *types.Var
|
// that we can analyze anonymous functions such as
|
||||||
args *types.Var
|
//
|
||||||
|
// printf := func(format string, args ...any) {...},
|
||||||
|
//
|
||||||
|
// representing them by the *types.Var symbol for the local variable
|
||||||
|
// 'printf'.
|
||||||
|
type wrapper struct {
|
||||||
|
obj types.Object // *Func or *Var
|
||||||
|
curBody inspector.Cursor // for *ast.BlockStmt
|
||||||
|
format *types.Var // optional "format string" parameter in the Func{Decl,Lit}
|
||||||
|
args *types.Var // "args ...any" parameter in the Func{Decl,Lit}
|
||||||
callers []printfCaller
|
callers []printfCaller
|
||||||
failed bool // if true, not a printf wrapper
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type printfCaller struct {
|
type printfCaller struct {
|
||||||
w *printfWrapper
|
w *wrapper
|
||||||
call *ast.CallExpr
|
call *ast.CallExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
// maybePrintfWrapper decides whether decl (a declared function) may be a wrapper
|
// formatArgsParams returns the "format string" and "args ...any"
|
||||||
// around a fmt.Printf or fmt.Print function. If so it returns a printfWrapper
|
// parameters of a potential print or printf wrapper function.
|
||||||
// function describing the declaration. Later processing will analyze the
|
// (The format is nil in the print-like case.)
|
||||||
// graph of potential printf wrappers to pick out the ones that are true wrappers.
|
func formatArgsParams(sig *types.Signature) (format, args *types.Var) {
|
||||||
// A function may be a Printf or Print wrapper if its last argument is ...interface{}.
|
|
||||||
// If the next-to-last argument is a string, then this may be a Printf wrapper.
|
|
||||||
// Otherwise it may be a Print wrapper.
|
|
||||||
func maybePrintfWrapper(info *types.Info, decl ast.Decl) *printfWrapper {
|
|
||||||
// Look for functions with final argument type ...interface{}.
|
|
||||||
fdecl, ok := decl.(*ast.FuncDecl)
|
|
||||||
if !ok || fdecl.Body == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
fn, ok := info.Defs[fdecl.Name].(*types.Func)
|
|
||||||
// Type information may be incomplete.
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
sig := fn.Type().(*types.Signature)
|
|
||||||
if !sig.Variadic() {
|
if !sig.Variadic() {
|
||||||
return nil // not variadic
|
return nil, nil // not variadic
|
||||||
}
|
}
|
||||||
|
|
||||||
params := sig.Params()
|
params := sig.Params()
|
||||||
nparams := params.Len() // variadic => nonzero
|
nparams := params.Len() // variadic => nonzero
|
||||||
|
|
||||||
// Check final parameter is "args ...interface{}".
|
|
||||||
args := params.At(nparams - 1)
|
|
||||||
iface, ok := types.Unalias(args.Type().(*types.Slice).Elem()).(*types.Interface)
|
|
||||||
if !ok || !iface.Empty() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is second last param 'format string'?
|
// Is second last param 'format string'?
|
||||||
var format *types.Var
|
|
||||||
if nparams >= 2 {
|
if nparams >= 2 {
|
||||||
if p := params.At(nparams - 2); p.Type() == types.Typ[types.String] {
|
if p := params.At(nparams - 2); p.Type() == types.Typ[types.String] {
|
||||||
format = p
|
format = p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &printfWrapper{
|
// Check final parameter is "args ...any".
|
||||||
obj: fn,
|
// (variadic => slice)
|
||||||
fdecl: fdecl,
|
args = params.At(nparams - 1)
|
||||||
format: format,
|
iface, ok := types.Unalias(args.Type().(*types.Slice).Elem()).(*types.Interface)
|
||||||
args: args,
|
if !ok || !iface.Empty() {
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return format, args
|
||||||
}
|
}
|
||||||
|
|
||||||
// findPrintfLike scans the entire package to find printf-like functions.
|
// findPrintLike scans the entire package to find print or printf-like functions.
|
||||||
func findPrintfLike(pass *analysis.Pass, res *Result) (any, error) {
|
// When it returns, all such functions have been identified.
|
||||||
// Gather potential wrappers and call graph between them.
|
func findPrintLike(pass *analysis.Pass, res *Result) {
|
||||||
byObj := make(map[*types.Func]*printfWrapper)
|
var (
|
||||||
var wrappers []*printfWrapper
|
inspect = pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||||
for _, file := range pass.Files {
|
info = pass.TypesInfo
|
||||||
for _, decl := range file.Decls {
|
)
|
||||||
w := maybePrintfWrapper(pass.TypesInfo, decl)
|
|
||||||
if w == nil {
|
// Pass 1: gather candidate wrapper functions (and populate wrappers).
|
||||||
continue
|
var (
|
||||||
|
wrappers []*wrapper
|
||||||
|
byObj = make(map[types.Object]*wrapper)
|
||||||
|
)
|
||||||
|
for cur := range inspect.Root().Preorder((*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)) {
|
||||||
|
var (
|
||||||
|
curBody inspector.Cursor // for *ast.BlockStmt
|
||||||
|
sig *types.Signature
|
||||||
|
obj types.Object
|
||||||
|
)
|
||||||
|
switch f := cur.Node().(type) {
|
||||||
|
case *ast.FuncDecl:
|
||||||
|
// named function or method:
|
||||||
|
//
|
||||||
|
// func wrapf(format string, args ...any) {...}
|
||||||
|
if f.Body != nil {
|
||||||
|
curBody = cur.ChildAt(edge.FuncDecl_Body, -1)
|
||||||
|
obj = info.Defs[f.Name]
|
||||||
|
sig = obj.Type().(*types.Signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.FuncLit:
|
||||||
|
// anonymous function directly assigned to a variable:
|
||||||
|
//
|
||||||
|
// var wrapf = func(format string, args ...any) {...}
|
||||||
|
// wrapf := func(format string, args ...any) {...}
|
||||||
|
// wrapf = func(format string, args ...any) {...}
|
||||||
|
//
|
||||||
|
// The LHS may also be a struct field x.wrapf or
|
||||||
|
// an imported var pkg.Wrapf.
|
||||||
|
//
|
||||||
|
sig = info.TypeOf(f).(*types.Signature)
|
||||||
|
curBody = cur.ChildAt(edge.FuncLit_Body, -1)
|
||||||
|
var lhs ast.Expr
|
||||||
|
switch ek, idx := cur.ParentEdge(); ek {
|
||||||
|
case edge.ValueSpec_Values:
|
||||||
|
curName := cur.Parent().ChildAt(edge.ValueSpec_Names, idx)
|
||||||
|
lhs = curName.Node().(*ast.Ident)
|
||||||
|
case edge.AssignStmt_Rhs:
|
||||||
|
curLhs := cur.Parent().ChildAt(edge.AssignStmt_Lhs, idx)
|
||||||
|
lhs = curLhs.Node().(ast.Expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch lhs := lhs.(type) {
|
||||||
|
case *ast.Ident:
|
||||||
|
// variable: wrapf = func(...)
|
||||||
|
obj = info.ObjectOf(lhs).(*types.Var)
|
||||||
|
case *ast.SelectorExpr:
|
||||||
|
if sel, ok := info.Selections[lhs]; ok {
|
||||||
|
// struct field: x.wrapf = func(...)
|
||||||
|
obj = sel.Obj().(*types.Var)
|
||||||
|
} else {
|
||||||
|
// imported var: pkg.Wrapf = func(...)
|
||||||
|
obj = info.Uses[lhs.Sel].(*types.Var)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if obj != nil {
|
||||||
|
format, args := formatArgsParams(sig)
|
||||||
|
if args != nil {
|
||||||
|
// obj (the symbol for a function/method, or variable
|
||||||
|
// assigned to an anonymous function) is a potential
|
||||||
|
// print or printf wrapper.
|
||||||
|
//
|
||||||
|
// Later processing will analyze the graph of potential
|
||||||
|
// wrappers and their function bodies to pick out the
|
||||||
|
// ones that are true wrappers.
|
||||||
|
w := &wrapper{
|
||||||
|
obj: obj,
|
||||||
|
curBody: curBody,
|
||||||
|
format: format, // non-nil => printf
|
||||||
|
args: args,
|
||||||
|
}
|
||||||
|
byObj[w.obj] = w
|
||||||
|
wrappers = append(wrappers, w)
|
||||||
}
|
}
|
||||||
byObj[w.obj] = w
|
|
||||||
wrappers = append(wrappers, w)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk the graph to figure out which are really printf wrappers.
|
// Pass 2: scan the body of each wrapper function
|
||||||
|
// for calls to other printf-like functions.
|
||||||
|
//
|
||||||
|
// Also, reject tricky cases where the parameters
|
||||||
|
// are potentially mutated by AssignStmt or UnaryExpr.
|
||||||
|
// TODO: Relax these checks; issue 26555.
|
||||||
for _, w := range wrappers {
|
for _, w := range wrappers {
|
||||||
// Scan function for calls that could be to other printf-like functions.
|
scan:
|
||||||
ast.Inspect(w.fdecl.Body, func(n ast.Node) bool {
|
for cur := range w.curBody.Preorder(
|
||||||
if w.failed {
|
(*ast.AssignStmt)(nil),
|
||||||
return false
|
(*ast.UnaryExpr)(nil),
|
||||||
}
|
(*ast.CallExpr)(nil),
|
||||||
|
) {
|
||||||
|
switch n := cur.Node().(type) {
|
||||||
|
case *ast.AssignStmt:
|
||||||
|
// If the wrapper updates format or args
|
||||||
|
// it is not a simple wrapper.
|
||||||
|
for _, lhs := range n.Lhs {
|
||||||
|
if w.format != nil && match(info, lhs, w.format) ||
|
||||||
|
match(info, lhs, w.args) {
|
||||||
|
break scan
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Relax these checks; issue 26555.
|
case *ast.UnaryExpr:
|
||||||
if assign, ok := n.(*ast.AssignStmt); ok {
|
// If the wrapper computes &format or &args,
|
||||||
for _, lhs := range assign.Lhs {
|
// it is not a simple wrapper.
|
||||||
if match(pass.TypesInfo, lhs, w.format) ||
|
if n.Op == token.AND &&
|
||||||
match(pass.TypesInfo, lhs, w.args) {
|
(w.format != nil && match(info, n.X, w.format) ||
|
||||||
// Modifies the format
|
match(info, n.X, w.args)) {
|
||||||
// string or args in
|
break scan
|
||||||
// some way, so not a
|
}
|
||||||
// simple wrapper.
|
|
||||||
w.failed = true
|
case *ast.CallExpr:
|
||||||
return false
|
if len(n.Args) > 0 && match(info, n.Args[len(n.Args)-1], w.args) {
|
||||||
|
if callee := typeutil.Callee(pass.TypesInfo, n); callee != nil {
|
||||||
|
|
||||||
|
// Call from one wrapper candidate to another?
|
||||||
|
// Record the edge so that if callee is found to be
|
||||||
|
// a true wrapper, w will be too.
|
||||||
|
if w2, ok := byObj[callee]; ok {
|
||||||
|
w2.callers = append(w2.callers, printfCaller{w, n})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the candidate a true wrapper, because it calls
|
||||||
|
// a known print{,f}-like function from the allowlist
|
||||||
|
// or an imported fact, or another wrapper found
|
||||||
|
// to be a true wrapper?
|
||||||
|
// If so, convert all w's callers to kind.
|
||||||
|
kind := callKind(pass, callee, res)
|
||||||
|
if kind != KindNone {
|
||||||
|
checkForward(pass, w, n, kind, res)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if un, ok := n.(*ast.UnaryExpr); ok && un.Op == token.AND {
|
}
|
||||||
if match(pass.TypesInfo, un.X, w.format) ||
|
|
||||||
match(pass.TypesInfo, un.X, w.args) {
|
|
||||||
// Taking the address of the
|
|
||||||
// format string or args,
|
|
||||||
// so not a simple wrapper.
|
|
||||||
w.failed = true
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
call, ok := n.(*ast.CallExpr)
|
|
||||||
if !ok || len(call.Args) == 0 || !match(pass.TypesInfo, call.Args[len(call.Args)-1], w.args) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn, kind := printfNameAndKind(pass, call)
|
|
||||||
if kind != 0 {
|
|
||||||
checkPrintfFwd(pass, w, call, kind, res)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the call is to another function in this package,
|
|
||||||
// maybe we will find out it is printf-like later.
|
|
||||||
// Remember this call for later checking.
|
|
||||||
if fn != nil && fn.Pkg() == pass.Pkg && byObj[fn] != nil {
|
|
||||||
callee := byObj[fn]
|
|
||||||
callee.callers = append(callee.callers, printfCaller{w, call})
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func match(info *types.Info, arg ast.Expr, param *types.Var) bool {
|
func match(info *types.Info, arg ast.Expr, param *types.Var) bool {
|
||||||
|
|
@ -261,9 +323,9 @@ func match(info *types.Info, arg ast.Expr, param *types.Var) bool {
|
||||||
return ok && info.ObjectOf(id) == param
|
return ok && info.ObjectOf(id) == param
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkPrintfFwd checks that a printf-forwarding wrapper is forwarding correctly.
|
// checkForward checks that a forwarding wrapper is forwarding correctly.
|
||||||
// It diagnoses writing fmt.Printf(format, args) instead of fmt.Printf(format, args...).
|
// It diagnoses writing fmt.Printf(format, args) instead of fmt.Printf(format, args...).
|
||||||
func checkPrintfFwd(pass *analysis.Pass, w *printfWrapper, call *ast.CallExpr, kind Kind, res *Result) {
|
func checkForward(pass *analysis.Pass, w *wrapper, call *ast.CallExpr, kind Kind, res *Result) {
|
||||||
matched := kind == KindPrint ||
|
matched := kind == KindPrint ||
|
||||||
kind != KindNone && len(call.Args) >= 2 && match(pass.TypesInfo, call.Args[len(call.Args)-2], w.format)
|
kind != KindNone && len(call.Args) >= 2 && match(pass.TypesInfo, call.Args[len(call.Args)-2], w.format)
|
||||||
if !matched {
|
if !matched {
|
||||||
|
|
@ -292,18 +354,39 @@ func checkPrintfFwd(pass *analysis.Pass, w *printfWrapper, call *ast.CallExpr, k
|
||||||
pass.ReportRangef(call, "missing ... in args forwarded to %s-like function", desc)
|
pass.ReportRangef(call, "missing ... in args forwarded to %s-like function", desc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fn := w.obj
|
|
||||||
var fact isWrapper
|
// If the candidate's print{,f} status becomes known,
|
||||||
if !pass.ImportObjectFact(fn, &fact) {
|
// propagate it back to all its so-far known callers.
|
||||||
fact.Kind = kind
|
if res.funcs[w.obj] != kind {
|
||||||
pass.ExportObjectFact(fn, &fact)
|
res.funcs[w.obj] = kind
|
||||||
res.funcs[fn] = kind
|
|
||||||
|
// Export a fact.
|
||||||
|
// (This is a no-op for local symbols.)
|
||||||
|
// We can't export facts on a symbol of another package,
|
||||||
|
// but we can treat the symbol as a wrapper within
|
||||||
|
// the current analysis unit.
|
||||||
|
if w.obj.Pkg() == pass.Pkg {
|
||||||
|
// Facts are associated with origins.
|
||||||
|
pass.ExportObjectFact(origin(w.obj), &isWrapper{Kind: kind})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Propagate kind back to known callers.
|
||||||
for _, caller := range w.callers {
|
for _, caller := range w.callers {
|
||||||
checkPrintfFwd(pass, caller.w, caller.call, kind, res)
|
checkForward(pass, caller.w, caller.call, kind, res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func origin(obj types.Object) types.Object {
|
||||||
|
switch obj := obj.(type) {
|
||||||
|
case *types.Func:
|
||||||
|
return obj.Origin()
|
||||||
|
case *types.Var:
|
||||||
|
return obj.Origin()
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
// isPrint records the print functions.
|
// isPrint records the print functions.
|
||||||
// If a key ends in 'f' then it is assumed to be a formatted print.
|
// If a key ends in 'f' then it is assumed to be a formatted print.
|
||||||
//
|
//
|
||||||
|
|
@ -412,7 +495,7 @@ func stringConstantExpr(pass *analysis.Pass, expr ast.Expr) (string, bool) {
|
||||||
|
|
||||||
// checkCalls triggers the print-specific checks for calls that invoke a print
|
// checkCalls triggers the print-specific checks for calls that invoke a print
|
||||||
// function.
|
// function.
|
||||||
func checkCalls(pass *analysis.Pass) {
|
func checkCalls(pass *analysis.Pass, res *Result) {
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||||
nodeFilter := []ast.Node{
|
nodeFilter := []ast.Node{
|
||||||
(*ast.File)(nil),
|
(*ast.File)(nil),
|
||||||
|
|
@ -426,48 +509,60 @@ func checkCalls(pass *analysis.Pass) {
|
||||||
fileVersion = versions.Lang(versions.FileVersion(pass.TypesInfo, n))
|
fileVersion = versions.Lang(versions.FileVersion(pass.TypesInfo, n))
|
||||||
|
|
||||||
case *ast.CallExpr:
|
case *ast.CallExpr:
|
||||||
fn, kind := printfNameAndKind(pass, n)
|
if callee := typeutil.Callee(pass.TypesInfo, n); callee != nil {
|
||||||
switch kind {
|
kind := callKind(pass, callee, res)
|
||||||
case KindPrintf, KindErrorf:
|
switch kind {
|
||||||
checkPrintf(pass, fileVersion, kind, n, fn.FullName())
|
case KindPrintf, KindErrorf:
|
||||||
case KindPrint:
|
checkPrintf(pass, fileVersion, kind, n, fullname(callee))
|
||||||
checkPrint(pass, n, fn.FullName())
|
case KindPrint:
|
||||||
|
checkPrint(pass, n, fullname(callee))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func printfNameAndKind(pass *analysis.Pass, call *ast.CallExpr) (fn *types.Func, kind Kind) {
|
func fullname(obj types.Object) string {
|
||||||
fn, _ = typeutil.Callee(pass.TypesInfo, call).(*types.Func)
|
if fn, ok := obj.(*types.Func); ok {
|
||||||
if fn == nil {
|
return fn.FullName()
|
||||||
return nil, 0
|
|
||||||
}
|
}
|
||||||
|
return obj.Name()
|
||||||
|
}
|
||||||
|
|
||||||
// Facts are associated with generic declarations, not instantiations.
|
// callKind returns the symbol of the called function
|
||||||
fn = fn.Origin()
|
// and its print/printf kind, if any.
|
||||||
|
// (The symbol may be a var for an anonymous function.)
|
||||||
_, ok := isPrint[fn.FullName()]
|
// The result is memoized in res.funcs.
|
||||||
|
func callKind(pass *analysis.Pass, obj types.Object, res *Result) Kind {
|
||||||
|
kind, ok := res.funcs[obj]
|
||||||
if !ok {
|
if !ok {
|
||||||
// Next look up just "printf", for use with -printf.funcs.
|
// cache miss
|
||||||
_, ok = isPrint[strings.ToLower(fn.Name())]
|
_, ok := isPrint[fullname(obj)]
|
||||||
}
|
if !ok {
|
||||||
if ok {
|
// Next look up just "printf", for use with -printf.funcs.
|
||||||
if fn.FullName() == "fmt.Errorf" {
|
_, ok = isPrint[strings.ToLower(obj.Name())]
|
||||||
kind = KindErrorf
|
|
||||||
} else if strings.HasSuffix(fn.Name(), "f") {
|
|
||||||
kind = KindPrintf
|
|
||||||
} else {
|
|
||||||
kind = KindPrint
|
|
||||||
}
|
}
|
||||||
return fn, kind
|
if ok {
|
||||||
|
// well-known printf functions
|
||||||
|
if fullname(obj) == "fmt.Errorf" {
|
||||||
|
kind = KindErrorf
|
||||||
|
} else if strings.HasSuffix(obj.Name(), "f") {
|
||||||
|
kind = KindPrintf
|
||||||
|
} else {
|
||||||
|
kind = KindPrint
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// imported wrappers
|
||||||
|
// Facts are associated with generic declarations, not instantiations.
|
||||||
|
obj = origin(obj)
|
||||||
|
var fact isWrapper
|
||||||
|
if pass.ImportObjectFact(obj, &fact) {
|
||||||
|
kind = fact.Kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.funcs[obj] = kind // cache
|
||||||
}
|
}
|
||||||
|
return kind
|
||||||
var fact isWrapper
|
|
||||||
if pass.ImportObjectFact(fn, &fact) {
|
|
||||||
return fn, fact.Kind
|
|
||||||
}
|
|
||||||
|
|
||||||
return fn, KindNone
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isFormatter reports whether t could satisfy fmt.Formatter.
|
// isFormatter reports whether t could satisfy fmt.Formatter.
|
||||||
|
|
@ -490,7 +585,7 @@ func isFormatter(typ types.Type) bool {
|
||||||
sig := fn.Type().(*types.Signature)
|
sig := fn.Type().(*types.Signature)
|
||||||
return sig.Params().Len() == 2 &&
|
return sig.Params().Len() == 2 &&
|
||||||
sig.Results().Len() == 0 &&
|
sig.Results().Len() == 0 &&
|
||||||
analysisinternal.IsTypeNamed(sig.Params().At(0).Type(), "fmt", "State") &&
|
typesinternal.IsTypeNamed(sig.Params().At(0).Type(), "fmt", "State") &&
|
||||||
types.Identical(sig.Params().At(1).Type(), types.Typ[types.Rune])
|
types.Identical(sig.Params().At(1).Type(), types.Typ[types.Rune])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -729,7 +824,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, ma
|
||||||
if reason != "" {
|
if reason != "" {
|
||||||
details = " (" + reason + ")"
|
details = " (" + reason + ")"
|
||||||
}
|
}
|
||||||
pass.ReportRangef(rng, "%s format %s uses non-int %s%s as argument of *", name, operation.Text, analysisinternal.Format(pass.Fset, arg), details)
|
pass.ReportRangef(rng, "%s format %s uses non-int %s%s as argument of *", name, operation.Text, astutil.Format(pass.Fset, arg), details)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -756,7 +851,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, ma
|
||||||
}
|
}
|
||||||
arg := call.Args[verbArgIndex]
|
arg := call.Args[verbArgIndex]
|
||||||
if isFunctionValue(pass, arg) && verb != 'p' && verb != 'T' {
|
if isFunctionValue(pass, arg) && verb != 'p' && verb != 'T' {
|
||||||
pass.ReportRangef(rng, "%s format %s arg %s is a func value, not called", name, operation.Text, analysisinternal.Format(pass.Fset, arg))
|
pass.ReportRangef(rng, "%s format %s arg %s is a func value, not called", name, operation.Text, astutil.Format(pass.Fset, arg))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if reason, ok := matchArgType(pass, v.typ, arg); !ok {
|
if reason, ok := matchArgType(pass, v.typ, arg); !ok {
|
||||||
|
|
@ -768,14 +863,14 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, rng analysis.Range, ma
|
||||||
if reason != "" {
|
if reason != "" {
|
||||||
details = " (" + reason + ")"
|
details = " (" + reason + ")"
|
||||||
}
|
}
|
||||||
pass.ReportRangef(rng, "%s format %s has arg %s of wrong type %s%s", name, operation.Text, analysisinternal.Format(pass.Fset, arg), typeString, details)
|
pass.ReportRangef(rng, "%s format %s has arg %s of wrong type %s%s", name, operation.Text, astutil.Format(pass.Fset, arg), typeString, details)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Detect recursive formatting via value's String/Error methods.
|
// Detect recursive formatting via value's String/Error methods.
|
||||||
// The '#' flag suppresses the methods, except with %x, %X, and %q.
|
// The '#' flag suppresses the methods, except with %x, %X, and %q.
|
||||||
if v.typ&argString != 0 && v.verb != 'T' && (!strings.Contains(operation.Flags, "#") || strings.ContainsRune("qxX", v.verb)) {
|
if v.typ&argString != 0 && v.verb != 'T' && (!strings.Contains(operation.Flags, "#") || strings.ContainsRune("qxX", v.verb)) {
|
||||||
if methodName, ok := recursiveStringer(pass, arg); ok {
|
if methodName, ok := recursiveStringer(pass, arg); ok {
|
||||||
pass.ReportRangef(rng, "%s format %s with arg %s causes recursive %s method call", name, operation.Text, analysisinternal.Format(pass.Fset, arg), methodName)
|
pass.ReportRangef(rng, "%s format %s with arg %s causes recursive %s method call", name, operation.Text, astutil.Format(pass.Fset, arg), methodName)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -927,7 +1022,7 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, name string) {
|
||||||
if sel, ok := call.Args[0].(*ast.SelectorExpr); ok {
|
if sel, ok := call.Args[0].(*ast.SelectorExpr); ok {
|
||||||
if x, ok := sel.X.(*ast.Ident); ok {
|
if x, ok := sel.X.(*ast.Ident); ok {
|
||||||
if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
|
if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
|
||||||
pass.ReportRangef(call, "%s does not take io.Writer but has first arg %s", name, analysisinternal.Format(pass.Fset, call.Args[0]))
|
pass.ReportRangef(call, "%s does not take io.Writer but has first arg %s", name, astutil.Format(pass.Fset, call.Args[0]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -961,10 +1056,10 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, name string) {
|
||||||
}
|
}
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
if isFunctionValue(pass, arg) {
|
if isFunctionValue(pass, arg) {
|
||||||
pass.ReportRangef(call, "%s arg %s is a func value, not called", name, analysisinternal.Format(pass.Fset, arg))
|
pass.ReportRangef(call, "%s arg %s is a func value, not called", name, astutil.Format(pass.Fset, arg))
|
||||||
}
|
}
|
||||||
if methodName, ok := recursiveStringer(pass, arg); ok {
|
if methodName, ok := recursiveStringer(pass, arg); ok {
|
||||||
pass.ReportRangef(call, "%s arg %s causes recursive call to %s method", name, analysisinternal.Format(pass.Fset, arg), methodName)
|
pass.ReportRangef(call, "%s arg %s causes recursive call to %s method", name, astutil.Format(pass.Fset, arg), methodName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift/shift.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/shift/shift.go
generated
vendored
|
|
@ -20,7 +20,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/astutil"
|
||||||
"golang.org/x/tools/internal/typeparams"
|
"golang.org/x/tools/internal/typeparams"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -123,7 +123,7 @@ func checkLongShift(pass *analysis.Pass, node ast.Node, x, y ast.Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if amt >= minSize {
|
if amt >= minSize {
|
||||||
ident := analysisinternal.Format(pass.Fset, x)
|
ident := astutil.Format(pass.Fset, x)
|
||||||
qualifier := ""
|
qualifier := ""
|
||||||
if len(sizes) > 1 {
|
if len(sizes) > 1 {
|
||||||
qualifier = "may be "
|
qualifier = "may be "
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/sigchanyzer/sigchanyzer.go
generated
vendored
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/sigchanyzer/sigchanyzer.go
generated
vendored
|
|
@ -18,9 +18,9 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -29,14 +29,14 @@ 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: analysisutil.MustExtractDoc(doc, "sigchanyzer"),
|
Doc: analysisinternal.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,
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
func run(pass *analysis.Pass) (any, error) {
|
||||||
if !analysisinternal.Imports(pass.Pkg, "os/signal") {
|
if !typesinternal.Imports(pass.Pkg, "os/signal") {
|
||||||
return nil, nil // doesn't directly import signal
|
return nil, nil // doesn't directly import signal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/slog/slog.go
generated
vendored
10
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/slog/slog.go
generated
vendored
|
|
@ -17,10 +17,10 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
"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: analysisutil.MustExtractDoc(doc, "slog"),
|
Doc: analysisinternal.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,
|
||||||
|
|
@ -115,10 +115,10 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
default:
|
default:
|
||||||
if unknownArg == nil {
|
if unknownArg == nil {
|
||||||
pass.ReportRangef(arg, "%s arg %q should be a string or a slog.Attr (possible missing key or value)",
|
pass.ReportRangef(arg, "%s arg %q should be a string or a slog.Attr (possible missing key or value)",
|
||||||
shortName(fn), analysisinternal.Format(pass.Fset, arg))
|
shortName(fn), astutil.Format(pass.Fset, arg))
|
||||||
} else {
|
} else {
|
||||||
pass.ReportRangef(arg, "%s arg %q should probably be a string or a slog.Attr (previous arg %q cannot be a key)",
|
pass.ReportRangef(arg, "%s arg %q should probably be a string or a slog.Attr (previous arg %q cannot be a key)",
|
||||||
shortName(fn), analysisinternal.Format(pass.Fset, arg), analysisinternal.Format(pass.Fset, unknownArg))
|
shortName(fn), astutil.Format(pass.Fset, arg), astutil.Format(pass.Fset, unknownArg))
|
||||||
}
|
}
|
||||||
// Stop here so we report at most one missing key per call.
|
// Stop here so we report at most one missing key per call.
|
||||||
return
|
return
|
||||||
|
|
@ -158,7 +158,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func isAttr(t types.Type) bool {
|
func isAttr(t types.Type) bool {
|
||||||
return analysisinternal.IsTypeNamed(t, "log/slog", "Attr")
|
return typesinternal.IsTypeNamed(t, "log/slog", "Attr")
|
||||||
}
|
}
|
||||||
|
|
||||||
// shortName returns a name for the function that is shorter than FullName.
|
// shortName returns a name for the function that is shorter than FullName.
|
||||||
|
|
|
||||||
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go
generated
vendored
4
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stdmethods/stdmethods.go
generated
vendored
|
|
@ -12,8 +12,8 @@ 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/analysisutil"
|
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
|
"golang.org/x/tools/internal/analysisinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
//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: analysisutil.MustExtractDoc(doc, "stdmethods"),
|
Doc: analysisinternal.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,
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go
generated
vendored
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go
generated
vendored
|
|
@ -13,9 +13,9 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
"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: analysisutil.MustExtractDoc(doc, "stringintconv"),
|
Doc: analysisinternal.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,
|
||||||
|
|
@ -198,7 +198,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
// the type has methods, as some {String,GoString,Format}
|
// the type has methods, as some {String,GoString,Format}
|
||||||
// may change the behavior of fmt.Sprint.
|
// may change the behavior of fmt.Sprint.
|
||||||
if len(ttypes) == 1 && len(vtypes) == 1 && types.NewMethodSet(V0).Len() == 0 {
|
if len(ttypes) == 1 && len(vtypes) == 1 && types.NewMethodSet(V0).Len() == 0 {
|
||||||
_, prefix, importEdits := analysisinternal.AddImport(pass.TypesInfo, file, "fmt", "fmt", "Sprint", arg.Pos())
|
prefix, importEdits := refactor.AddImport(pass.TypesInfo, file, "fmt", "fmt", "Sprint", arg.Pos())
|
||||||
if types.Identical(T0, types.Typ[types.String]) {
|
if types.Identical(T0, types.Typ[types.String]) {
|
||||||
// string(x) -> fmt.Sprint(x)
|
// string(x) -> fmt.Sprint(x)
|
||||||
addFix("Format the number as a decimal", append(importEdits,
|
addFix("Format the number as a decimal", append(importEdits,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
|
@ -31,7 +30,7 @@ func init() {
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "testinggoroutine",
|
Name: "testinggoroutine",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "testinggoroutine"),
|
Doc: analysisinternal.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,
|
||||||
|
|
@ -40,7 +39,7 @@ var Analyzer = &analysis.Analyzer{
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
func run(pass *analysis.Pass) (any, error) {
|
||||||
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||||
|
|
||||||
if !analysisinternal.Imports(pass.Pkg, "testing") {
|
if !typesinternal.Imports(pass.Pkg, "testing") {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go
generated
vendored
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go
generated
vendored
|
|
@ -15,8 +15,8 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
|
|
||||||
"golang.org/x/tools/internal/analysisinternal"
|
"golang.org/x/tools/internal/analysisinternal"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -24,7 +24,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "tests",
|
Name: "tests",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "tests"),
|
Doc: analysisinternal.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,
|
||||||
}
|
}
|
||||||
|
|
@ -258,7 +258,7 @@ func isTestingType(typ types.Type, testingType string) bool {
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return analysisinternal.IsTypeNamed(ptr.Elem(), "testing", testingType)
|
return typesinternal.IsTypeNamed(ptr.Elem(), "testing", testingType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate that fuzz target function's arguments are of accepted types.
|
// Validate that fuzz target function's arguments are of accepted types.
|
||||||
|
|
|
||||||
10
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/timeformat/timeformat.go
generated
vendored
10
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/timeformat/timeformat.go
generated
vendored
|
|
@ -16,10 +16,10 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
const badFormat = "2006-02-01"
|
const badFormat = "2006-02-01"
|
||||||
|
|
@ -30,7 +30,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "timeformat",
|
Name: "timeformat",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "timeformat"),
|
Doc: analysisinternal.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 !analysisutil.Imports(pass.Pkg, "time").
|
// when !analysisinternal.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)
|
||||||
|
|
@ -50,8 +50,8 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
inspect.Preorder(nodeFilter, func(n ast.Node) {
|
inspect.Preorder(nodeFilter, func(n ast.Node) {
|
||||||
call := n.(*ast.CallExpr)
|
call := n.(*ast.CallExpr)
|
||||||
obj := typeutil.Callee(pass.TypesInfo, call)
|
obj := typeutil.Callee(pass.TypesInfo, call)
|
||||||
if !analysisinternal.IsMethodNamed(obj, "time", "Time", "Format") &&
|
if !typesinternal.IsMethodNamed(obj, "time", "Time", "Format") &&
|
||||||
!analysisinternal.IsFunctionNamed(obj, "time", "Parse") {
|
!typesinternal.IsFunctionNamed(obj, "time", "Parse") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(call.Args) > 0 {
|
if len(call.Args) > 0 {
|
||||||
|
|
|
||||||
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal/unmarshal.go
generated
vendored
6
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unmarshal/unmarshal.go
generated
vendored
|
|
@ -11,9 +11,9 @@ 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/analysisutil"
|
|
||||||
"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/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: analysisutil.MustExtractDoc(doc, "unmarshal"),
|
Doc: analysisinternal.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 !analysisutil.Imports(pass.Pkg, "encoding/...").
|
// when !analysisinternal.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)
|
||||||
|
|
|
||||||
17
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unreachable/unreachable.go
generated
vendored
17
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unreachable/unreachable.go
generated
vendored
|
|
@ -14,8 +14,9 @@ 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/analysisutil"
|
|
||||||
"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/refactor"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -23,7 +24,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "unreachable",
|
Name: "unreachable",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "unreachable"),
|
Doc: analysisinternal.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,
|
||||||
|
|
@ -188,6 +189,11 @@ func (d *deadState) findDead(stmt ast.Stmt) {
|
||||||
case *ast.EmptyStmt:
|
case *ast.EmptyStmt:
|
||||||
// do not warn about unreachable empty statements
|
// do not warn about unreachable empty statements
|
||||||
default:
|
default:
|
||||||
|
var (
|
||||||
|
inspect = d.pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||||
|
curStmt, _ = inspect.Root().FindNode(stmt)
|
||||||
|
tokFile = d.pass.Fset.File(stmt.Pos())
|
||||||
|
)
|
||||||
// (This call to pass.Report is a frequent source
|
// (This call to pass.Report is a frequent source
|
||||||
// of diagnostics beyond EOF in a truncated file;
|
// of diagnostics beyond EOF in a truncated file;
|
||||||
// see #71659.)
|
// see #71659.)
|
||||||
|
|
@ -196,11 +202,8 @@ func (d *deadState) findDead(stmt ast.Stmt) {
|
||||||
End: stmt.End(),
|
End: stmt.End(),
|
||||||
Message: "unreachable code",
|
Message: "unreachable code",
|
||||||
SuggestedFixes: []analysis.SuggestedFix{{
|
SuggestedFixes: []analysis.SuggestedFix{{
|
||||||
Message: "Remove",
|
Message: "Remove",
|
||||||
TextEdits: []analysis.TextEdit{{
|
TextEdits: refactor.DeleteStmt(tokFile, curStmt),
|
||||||
Pos: stmt.Pos(),
|
|
||||||
End: stmt.End(),
|
|
||||||
}},
|
|
||||||
}},
|
}},
|
||||||
})
|
})
|
||||||
d.reachable = true // silence error about next statement
|
d.reachable = true // silence error about next statement
|
||||||
|
|
|
||||||
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unsafeptr/unsafeptr.go
generated
vendored
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unsafeptr/unsafeptr.go
generated
vendored
|
|
@ -14,9 +14,9 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -24,7 +24,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "unsafeptr",
|
Name: "unsafeptr",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "unsafeptr"),
|
Doc: analysisinternal.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,
|
||||||
|
|
@ -105,7 +105,7 @@ func isSafeUintptr(info *types.Info, x ast.Expr) bool {
|
||||||
}
|
}
|
||||||
switch sel.Sel.Name {
|
switch sel.Sel.Name {
|
||||||
case "Pointer", "UnsafeAddr":
|
case "Pointer", "UnsafeAddr":
|
||||||
if analysisinternal.IsTypeNamed(info.Types[sel.X].Type, "reflect", "Value") {
|
if typesinternal.IsTypeNamed(info.Types[sel.X].Type, "reflect", "Value") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -153,5 +153,5 @@ func hasBasicType(info *types.Info, x ast.Expr, kind types.BasicKind) bool {
|
||||||
|
|
||||||
// isReflectHeader reports whether t is reflect.SliceHeader or reflect.StringHeader.
|
// isReflectHeader reports whether t is reflect.SliceHeader or reflect.StringHeader.
|
||||||
func isReflectHeader(t types.Type) bool {
|
func isReflectHeader(t types.Type) bool {
|
||||||
return analysisinternal.IsTypeNamed(t, "reflect", "SliceHeader", "StringHeader")
|
return typesinternal.IsTypeNamed(t, "reflect", "SliceHeader", "StringHeader")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go
generated
vendored
3
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go
generated
vendored
|
|
@ -23,7 +23,6 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
|
@ -34,7 +33,7 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "unusedresult",
|
Name: "unusedresult",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "unusedresult"),
|
Doc: analysisinternal.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,
|
||||||
|
|
|
||||||
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/waitgroup/waitgroup.go
generated
vendored
8
src/cmd/vendor/golang.org/x/tools/go/analysis/passes/waitgroup/waitgroup.go
generated
vendored
|
|
@ -13,10 +13,10 @@ 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/analysisutil"
|
|
||||||
"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/analysisinternal"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed doc.go
|
//go:embed doc.go
|
||||||
|
|
@ -24,14 +24,14 @@ var doc string
|
||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "waitgroup",
|
Name: "waitgroup",
|
||||||
Doc: analysisutil.MustExtractDoc(doc, "waitgroup"),
|
Doc: analysisinternal.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,
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
func run(pass *analysis.Pass) (any, error) {
|
||||||
if !analysisinternal.Imports(pass.Pkg, "sync") {
|
if !typesinternal.Imports(pass.Pkg, "sync") {
|
||||||
return nil, nil // doesn't directly import sync
|
return nil, nil // doesn't directly import sync
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ func run(pass *analysis.Pass) (any, error) {
|
||||||
if push {
|
if push {
|
||||||
call := n.(*ast.CallExpr)
|
call := n.(*ast.CallExpr)
|
||||||
obj := typeutil.Callee(pass.TypesInfo, call)
|
obj := typeutil.Callee(pass.TypesInfo, call)
|
||||||
if analysisinternal.IsMethodNamed(obj, "sync", "WaitGroup", "Add") &&
|
if typesinternal.IsMethodNamed(obj, "sync", "WaitGroup", "Add") &&
|
||||||
hasSuffix(stack, wantSuffix) &&
|
hasSuffix(stack, wantSuffix) &&
|
||||||
backindex(stack, 1) == backindex(stack, 2).(*ast.BlockStmt).List[0] { // ExprStmt must be Block's first stmt
|
backindex(stack, 1) == backindex(stack, 2).(*ast.BlockStmt).List[0] { // ExprStmt must be Block's first stmt
|
||||||
|
|
||||||
|
|
|
||||||
20
src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go
generated
vendored
20
src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go
generated
vendored
|
|
@ -75,7 +75,6 @@ type Config struct {
|
||||||
VetxOutput string // where to write file of fact information
|
VetxOutput string // where to write file of fact information
|
||||||
Stdout string // write stdout (e.g. JSON, unified diff) to this file
|
Stdout string // write stdout (e.g. JSON, unified diff) to this file
|
||||||
SucceedOnTypecheckFailure bool // obsolete awful hack; see #18395 and below
|
SucceedOnTypecheckFailure bool // obsolete awful hack; see #18395 and below
|
||||||
WarnDiagnostics bool // printing diagnostics should not cause a non-zero exit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main is the main function of a vet-like analysis tool that must be
|
// Main is the main function of a vet-like analysis tool that must be
|
||||||
|
|
@ -87,18 +86,9 @@ type Config struct {
|
||||||
// -V=full describe executable for build caching
|
// -V=full describe executable for build caching
|
||||||
// foo.cfg perform separate modular analyze on the single
|
// foo.cfg perform separate modular analyze on the single
|
||||||
// unit described by a JSON config file foo.cfg.
|
// unit described by a JSON config file foo.cfg.
|
||||||
//
|
|
||||||
// Also, subject to approval of proposal #71859:
|
|
||||||
//
|
|
||||||
// -fix don't print each diagnostic, apply its first fix
|
// -fix don't print each diagnostic, apply its first fix
|
||||||
// -diff don't apply a fix, print the diff (requires -fix)
|
// -diff don't apply a fix, print the diff (requires -fix)
|
||||||
//
|
// -json print diagnostics and fixes in JSON form
|
||||||
// Additionally, the environment variable GOVET has the value "vet" or
|
|
||||||
// "fix" depending on whether the command is being invoked by "go vet",
|
|
||||||
// to report diagnostics, or "go fix", to apply fixes. This is
|
|
||||||
// necessary so that callers of Main can select their analyzer suite
|
|
||||||
// before flag parsing. (Vet analyzers must report real code problems,
|
|
||||||
// whereas Fix analyzers may fix non-problems such as style issues.)
|
|
||||||
func Main(analyzers ...*analysis.Analyzer) {
|
func Main(analyzers ...*analysis.Analyzer) {
|
||||||
progname := filepath.Base(os.Args[0])
|
progname := filepath.Base(os.Args[0])
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
|
|
@ -163,7 +153,7 @@ func Run(configFile string, analyzers []*analysis.Analyzer) {
|
||||||
|
|
||||||
// In VetxOnly mode, the analysis is run only for facts.
|
// In VetxOnly mode, the analysis is run only for facts.
|
||||||
if !cfg.VetxOnly {
|
if !cfg.VetxOnly {
|
||||||
code = processResults(fset, cfg.ID, results, cfg.WarnDiagnostics)
|
code = processResults(fset, cfg.ID, results)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
|
|
@ -187,7 +177,7 @@ func readConfig(filename string) (*Config, error) {
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func processResults(fset *token.FileSet, id string, results []result, warnDiagnostics bool) (exit int) {
|
func processResults(fset *token.FileSet, id string, results []result) (exit int) {
|
||||||
if analysisflags.Fix {
|
if analysisflags.Fix {
|
||||||
// Don't print the diagnostics,
|
// Don't print the diagnostics,
|
||||||
// but apply all fixes from the root actions.
|
// but apply all fixes from the root actions.
|
||||||
|
|
@ -236,9 +226,7 @@ func processResults(fset *token.FileSet, id string, results []result, warnDiagno
|
||||||
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)
|
analysisflags.PrintPlain(os.Stderr, fset, analysisflags.Context, diag)
|
||||||
if !warnDiagnostics {
|
exit = 1
|
||||||
exit = 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
540
src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go
generated
vendored
540
src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go
generated
vendored
|
|
@ -2,166 +2,39 @@
|
||||||
// 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 provides gopls' internal analyses with a
|
// Package analysisinternal provides helper functions for use in both
|
||||||
// number of helper functions that operate on typed syntax trees.
|
// the analysis drivers in go/analysis and gopls, and in various
|
||||||
|
// analyzers.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): this is not ideal as it may lead to unnecessary
|
||||||
|
// dependencies between drivers and analyzers. Split into analyzerlib
|
||||||
|
// and driverlib?
|
||||||
package analysisinternal
|
package analysisinternal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"cmp"
|
"cmp"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
|
||||||
"go/printer"
|
|
||||||
"go/scanner"
|
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"os"
|
||||||
"iter"
|
|
||||||
pathpkg "path"
|
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
"golang.org/x/tools/go/ast/inspector"
|
|
||||||
"golang.org/x/tools/internal/moreiters"
|
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Deprecated: this heuristic is ill-defined.
|
// ReadFile reads a file and adds it to the FileSet in pass
|
||||||
// TODO(adonovan): move to sole use in gopls/internal/cache.
|
// so that we can report errors against it using lineStart.
|
||||||
func TypeErrorEndPos(fset *token.FileSet, src []byte, start token.Pos) token.Pos {
|
func ReadFile(pass *analysis.Pass, filename string) ([]byte, *token.File, error) {
|
||||||
// Get the end position for the type error.
|
readFile := pass.ReadFile
|
||||||
file := fset.File(start)
|
if readFile == nil {
|
||||||
if file == nil {
|
readFile = os.ReadFile
|
||||||
return start
|
|
||||||
}
|
}
|
||||||
if offset := file.PositionFor(start, false).Offset; offset > len(src) {
|
content, err := readFile(filename)
|
||||||
return start
|
if err != nil {
|
||||||
} else {
|
return nil, nil, err
|
||||||
src = src[offset:]
|
|
||||||
}
|
}
|
||||||
|
tf := pass.Fset.AddFile(filename, -1, len(content))
|
||||||
// Attempt to find a reasonable end position for the type error.
|
tf.SetLinesForContent(content)
|
||||||
//
|
return content, tf, nil
|
||||||
// TODO(rfindley): the heuristic implemented here is unclear. It looks like
|
|
||||||
// it seeks the end of the primary operand starting at start, but that is not
|
|
||||||
// quite implemented (for example, given a func literal this heuristic will
|
|
||||||
// return the range of the func keyword).
|
|
||||||
//
|
|
||||||
// We should formalize this heuristic, or deprecate it by finally proposing
|
|
||||||
// to add end position to all type checker errors.
|
|
||||||
//
|
|
||||||
// Nevertheless, ensure that the end position at least spans the current
|
|
||||||
// token at the cursor (this was golang/go#69505).
|
|
||||||
end := start
|
|
||||||
{
|
|
||||||
var s scanner.Scanner
|
|
||||||
fset := token.NewFileSet()
|
|
||||||
f := fset.AddFile("", fset.Base(), len(src))
|
|
||||||
s.Init(f, src, nil /* no error handler */, scanner.ScanComments)
|
|
||||||
pos, tok, lit := s.Scan()
|
|
||||||
if tok != token.SEMICOLON && token.Pos(f.Base()) <= pos && pos <= token.Pos(f.Base()+f.Size()) {
|
|
||||||
off := file.Offset(pos) + len(lit)
|
|
||||||
src = src[off:]
|
|
||||||
end += token.Pos(off)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for bytes that might terminate the current operand. See note above:
|
|
||||||
// this is imprecise.
|
|
||||||
if width := bytes.IndexAny(src, " \n,():;[]+-*/"); width > 0 {
|
|
||||||
end += token.Pos(width)
|
|
||||||
}
|
|
||||||
return end
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatchingIdents finds the names of all identifiers in 'node' that match any of the given types.
|
|
||||||
// 'pos' represents the position at which the identifiers may be inserted. 'pos' must be within
|
|
||||||
// the scope of each of identifier we select. Otherwise, we will insert a variable at 'pos' that
|
|
||||||
// is unrecognized.
|
|
||||||
func MatchingIdents(typs []types.Type, node ast.Node, pos token.Pos, info *types.Info, pkg *types.Package) map[types.Type][]string {
|
|
||||||
|
|
||||||
// Initialize matches to contain the variable types we are searching for.
|
|
||||||
matches := make(map[types.Type][]string)
|
|
||||||
for _, typ := range typs {
|
|
||||||
if typ == nil {
|
|
||||||
continue // TODO(adonovan): is this reachable?
|
|
||||||
}
|
|
||||||
matches[typ] = nil // create entry
|
|
||||||
}
|
|
||||||
|
|
||||||
seen := map[types.Object]struct{}{}
|
|
||||||
ast.Inspect(node, func(n ast.Node) bool {
|
|
||||||
if n == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Prevent circular definitions. If 'pos' is within an assignment statement, do not
|
|
||||||
// allow any identifiers in that assignment statement to be selected. Otherwise,
|
|
||||||
// we could do the following, where 'x' satisfies the type of 'f0':
|
|
||||||
//
|
|
||||||
// x := fakeStruct{f0: x}
|
|
||||||
//
|
|
||||||
if assign, ok := n.(*ast.AssignStmt); ok && pos > assign.Pos() && pos <= assign.End() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if n.End() > pos {
|
|
||||||
return n.Pos() <= pos
|
|
||||||
}
|
|
||||||
ident, ok := n.(*ast.Ident)
|
|
||||||
if !ok || ident.Name == "_" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
obj := info.Defs[ident]
|
|
||||||
if obj == nil || obj.Type() == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if _, ok := obj.(*types.TypeName); ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// Prevent duplicates in matches' values.
|
|
||||||
if _, ok = seen[obj]; ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
seen[obj] = struct{}{}
|
|
||||||
// Find the scope for the given position. Then, check whether the object
|
|
||||||
// exists within the scope.
|
|
||||||
innerScope := pkg.Scope().Innermost(pos)
|
|
||||||
if innerScope == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
_, foundObj := innerScope.LookupParent(ident.Name, pos)
|
|
||||||
if foundObj != obj {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// The object must match one of the types that we are searching for.
|
|
||||||
// TODO(adonovan): opt: use typeutil.Map?
|
|
||||||
if names, ok := matches[obj.Type()]; ok {
|
|
||||||
matches[obj.Type()] = append(names, ident.Name)
|
|
||||||
} else {
|
|
||||||
// If the object type does not exactly match
|
|
||||||
// any of the target types, greedily find the first
|
|
||||||
// target type that the object type can satisfy.
|
|
||||||
for typ := range matches {
|
|
||||||
if equivalentTypes(obj.Type(), typ) {
|
|
||||||
matches[typ] = append(matches[typ], ident.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
return matches
|
|
||||||
}
|
|
||||||
|
|
||||||
func equivalentTypes(want, got types.Type) bool {
|
|
||||||
if types.Identical(want, got) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// Code segment to help check for untyped equality from (golang/go#32146).
|
|
||||||
if rhs, ok := want.(*types.Basic); ok && rhs.Info()&types.IsUntyped > 0 {
|
|
||||||
if lhs, ok := got.Underlying().(*types.Basic); ok {
|
|
||||||
return rhs.Info()&types.IsConstType == lhs.Info()&types.IsConstType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return types.AssignableTo(want, got)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A ReadFileFunc is a function that returns the
|
// A ReadFileFunc is a function that returns the
|
||||||
|
|
@ -193,207 +66,6 @@ func CheckReadable(pass *analysis.Pass, filename string) error {
|
||||||
return fmt.Errorf("Pass.ReadFile: %s is not among OtherFiles, IgnoredFiles, or names of Files", filename)
|
return fmt.Errorf("Pass.ReadFile: %s is not among OtherFiles, IgnoredFiles, or names of Files", filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddImport checks whether this file already imports pkgpath and that
|
|
||||||
// the import is in scope at pos. If so, it returns the name under
|
|
||||||
// which it was imported and no edits. Otherwise, it adds a new import
|
|
||||||
// of pkgpath, using a name derived from the preferred name, and
|
|
||||||
// returns the chosen name, a prefix to be concatenated with member to
|
|
||||||
// form a qualified name, and the edit for the new import.
|
|
||||||
//
|
|
||||||
// The member argument indicates the name of the desired symbol within
|
|
||||||
// the imported package. This is needed in the case when the existing
|
|
||||||
// import is a dot import, because then it is possible that the
|
|
||||||
// desired symbol is shadowed by other declarations in the current
|
|
||||||
// package. If member is not shadowed at pos, AddImport returns (".",
|
|
||||||
// "", nil). (AddImport accepts the caller's implicit claim that the
|
|
||||||
// imported package declares member.)
|
|
||||||
//
|
|
||||||
// Use a preferredName of "_" to request a blank import;
|
|
||||||
// member is ignored in this case.
|
|
||||||
//
|
|
||||||
// It does not mutate its arguments.
|
|
||||||
func AddImport(info *types.Info, file *ast.File, preferredName, pkgpath, member string, pos token.Pos) (name, prefix string, newImport []analysis.TextEdit) {
|
|
||||||
// Find innermost enclosing lexical block.
|
|
||||||
scope := info.Scopes[file].Innermost(pos)
|
|
||||||
if scope == nil {
|
|
||||||
panic("no enclosing lexical block")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is there an existing import of this package?
|
|
||||||
// If so, are we in its scope? (not shadowed)
|
|
||||||
for _, spec := range file.Imports {
|
|
||||||
pkgname := info.PkgNameOf(spec)
|
|
||||||
if pkgname != nil && pkgname.Imported().Path() == pkgpath {
|
|
||||||
name = pkgname.Name()
|
|
||||||
if preferredName == "_" {
|
|
||||||
// Request for blank import; any existing import will do.
|
|
||||||
return name, "", nil
|
|
||||||
}
|
|
||||||
if name == "." {
|
|
||||||
// The scope of ident must be the file scope.
|
|
||||||
if s, _ := scope.LookupParent(member, pos); s == info.Scopes[file] {
|
|
||||||
return name, "", nil
|
|
||||||
}
|
|
||||||
} else if _, obj := scope.LookupParent(name, pos); obj == pkgname {
|
|
||||||
return name, name + ".", nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We must add a new import.
|
|
||||||
|
|
||||||
// Ensure we have a fresh name.
|
|
||||||
newName := preferredName
|
|
||||||
if preferredName != "_" {
|
|
||||||
newName = FreshName(scope, pos, preferredName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new import declaration either before the first existing
|
|
||||||
// declaration (which must exist), including its comments; or
|
|
||||||
// inside the declaration, if it is an import group.
|
|
||||||
//
|
|
||||||
// Use a renaming import whenever the preferred name is not
|
|
||||||
// available, or the chosen name does not match the last
|
|
||||||
// segment of its path.
|
|
||||||
newText := fmt.Sprintf("%q", pkgpath)
|
|
||||||
if newName != preferredName || newName != pathpkg.Base(pkgpath) {
|
|
||||||
newText = fmt.Sprintf("%s %q", newName, pkgpath)
|
|
||||||
}
|
|
||||||
|
|
||||||
decl0 := file.Decls[0]
|
|
||||||
var before ast.Node = decl0
|
|
||||||
switch decl0 := decl0.(type) {
|
|
||||||
case *ast.GenDecl:
|
|
||||||
if decl0.Doc != nil {
|
|
||||||
before = decl0.Doc
|
|
||||||
}
|
|
||||||
case *ast.FuncDecl:
|
|
||||||
if decl0.Doc != nil {
|
|
||||||
before = decl0.Doc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if gd, ok := before.(*ast.GenDecl); ok && gd.Tok == token.IMPORT && gd.Rparen.IsValid() {
|
|
||||||
// Have existing grouped import ( ... ) decl.
|
|
||||||
if IsStdPackage(pkgpath) && len(gd.Specs) > 0 {
|
|
||||||
// Add spec for a std package before
|
|
||||||
// first existing spec, followed by
|
|
||||||
// a blank line if the next one is non-std.
|
|
||||||
first := gd.Specs[0].(*ast.ImportSpec)
|
|
||||||
pos = first.Pos()
|
|
||||||
if !IsStdPackage(first.Path.Value) {
|
|
||||||
newText += "\n"
|
|
||||||
}
|
|
||||||
newText += "\n\t"
|
|
||||||
} else {
|
|
||||||
// Add spec at end of group.
|
|
||||||
pos = gd.Rparen
|
|
||||||
newText = "\t" + newText + "\n"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No import decl, or non-grouped import.
|
|
||||||
// Add a new import decl before first decl.
|
|
||||||
// (gofmt will merge multiple import decls.)
|
|
||||||
pos = before.Pos()
|
|
||||||
newText = "import " + newText + "\n\n"
|
|
||||||
}
|
|
||||||
return newName, newName + ".", []analysis.TextEdit{{
|
|
||||||
Pos: pos,
|
|
||||||
End: pos,
|
|
||||||
NewText: []byte(newText),
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FreshName returns the name of an identifier that is undefined
|
|
||||||
// at the specified position, based on the preferred name.
|
|
||||||
func FreshName(scope *types.Scope, pos token.Pos, preferred string) string {
|
|
||||||
newName := preferred
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
if _, obj := scope.LookupParent(newName, pos); obj == nil {
|
|
||||||
break // fresh
|
|
||||||
}
|
|
||||||
newName = fmt.Sprintf("%s%d", preferred, i)
|
|
||||||
}
|
|
||||||
return newName
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format returns a string representation of the node n.
|
|
||||||
func Format(fset *token.FileSet, n ast.Node) string {
|
|
||||||
var buf strings.Builder
|
|
||||||
printer.Fprint(&buf, fset, n) // ignore errors
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Imports returns true if path is imported by pkg.
|
|
||||||
func Imports(pkg *types.Package, path string) bool {
|
|
||||||
for _, imp := range pkg.Imports() {
|
|
||||||
if imp.Path() == path {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsTypeNamed reports whether t is (or is an alias for) a
|
|
||||||
// package-level defined type with the given package path and one of
|
|
||||||
// the given names. It returns false if t is nil.
|
|
||||||
//
|
|
||||||
// This function avoids allocating the concatenation of "pkg.Name",
|
|
||||||
// which is important for the performance of syntax matching.
|
|
||||||
func IsTypeNamed(t types.Type, pkgPath string, names ...string) bool {
|
|
||||||
if named, ok := types.Unalias(t).(*types.Named); ok {
|
|
||||||
tname := named.Obj()
|
|
||||||
return tname != nil &&
|
|
||||||
typesinternal.IsPackageLevel(tname) &&
|
|
||||||
tname.Pkg().Path() == pkgPath &&
|
|
||||||
slices.Contains(names, tname.Name())
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPointerToNamed reports whether t is (or is an alias for) a pointer to a
|
|
||||||
// package-level defined type with the given package path and one of the given
|
|
||||||
// names. It returns false if t is not a pointer type.
|
|
||||||
func IsPointerToNamed(t types.Type, pkgPath string, names ...string) bool {
|
|
||||||
r := typesinternal.Unpointer(t)
|
|
||||||
if r == t {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return IsTypeNamed(r, pkgPath, names...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFunctionNamed reports whether obj is a package-level function
|
|
||||||
// defined in the given package and has one of the given names.
|
|
||||||
// It returns false if obj is nil.
|
|
||||||
//
|
|
||||||
// This function avoids allocating the concatenation of "pkg.Name",
|
|
||||||
// which is important for the performance of syntax matching.
|
|
||||||
func IsFunctionNamed(obj types.Object, pkgPath string, names ...string) bool {
|
|
||||||
f, ok := obj.(*types.Func)
|
|
||||||
return ok &&
|
|
||||||
typesinternal.IsPackageLevel(obj) &&
|
|
||||||
f.Pkg().Path() == pkgPath &&
|
|
||||||
f.Type().(*types.Signature).Recv() == nil &&
|
|
||||||
slices.Contains(names, f.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsMethodNamed reports whether obj is a method defined on a
|
|
||||||
// package-level type with the given package and type name, and has
|
|
||||||
// one of the given names. It returns false if obj is nil.
|
|
||||||
//
|
|
||||||
// This function avoids allocating the concatenation of "pkg.TypeName.Name",
|
|
||||||
// which is important for the performance of syntax matching.
|
|
||||||
func IsMethodNamed(obj types.Object, pkgPath string, typeName string, names ...string) bool {
|
|
||||||
if fn, ok := obj.(*types.Func); ok {
|
|
||||||
if recv := fn.Type().(*types.Signature).Recv(); recv != nil {
|
|
||||||
_, T := typesinternal.ReceiverNamed(recv)
|
|
||||||
return T != nil &&
|
|
||||||
IsTypeNamed(T, pkgPath, typeName) &&
|
|
||||||
slices.Contains(names, fn.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateFixes validates the set of fixes for a single diagnostic.
|
// ValidateFixes validates the set of fixes for a single diagnostic.
|
||||||
// Any error indicates a bug in the originating analyzer.
|
// Any error indicates a bug in the originating analyzer.
|
||||||
//
|
//
|
||||||
|
|
@ -496,172 +168,6 @@ func validateFix(fset *token.FileSet, fix *analysis.SuggestedFix) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanImport reports whether one package is allowed to import another.
|
|
||||||
//
|
|
||||||
// TODO(adonovan): allow customization of the accessibility relation
|
|
||||||
// (e.g. for Bazel).
|
|
||||||
func CanImport(from, to string) bool {
|
|
||||||
// TODO(adonovan): better segment hygiene.
|
|
||||||
if to == "internal" || strings.HasPrefix(to, "internal/") {
|
|
||||||
// Special case: only std packages may import internal/...
|
|
||||||
// We can't reliably know whether we're in std, so we
|
|
||||||
// use a heuristic on the first segment.
|
|
||||||
first, _, _ := strings.Cut(from, "/")
|
|
||||||
if strings.Contains(first, ".") {
|
|
||||||
return false // example.com/foo ∉ std
|
|
||||||
}
|
|
||||||
if first == "testdata" {
|
|
||||||
return false // testdata/foo ∉ std
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(to, "/internal") {
|
|
||||||
return strings.HasPrefix(from, to[:len(to)-len("/internal")])
|
|
||||||
}
|
|
||||||
if i := strings.LastIndex(to, "/internal/"); i >= 0 {
|
|
||||||
return strings.HasPrefix(from, to[:i])
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteStmt returns the edits to remove the [ast.Stmt] identified by
|
|
||||||
// curStmt, if it is contained within a BlockStmt, CaseClause,
|
|
||||||
// CommClause, or is the STMT in switch STMT; ... {...}. It returns nil otherwise.
|
|
||||||
func DeleteStmt(fset *token.FileSet, curStmt inspector.Cursor) []analysis.TextEdit {
|
|
||||||
stmt := curStmt.Node().(ast.Stmt)
|
|
||||||
// if the stmt is on a line by itself delete the whole line
|
|
||||||
// otherwise just delete the statement.
|
|
||||||
|
|
||||||
// this logic would be a lot simpler with the file contents, and somewhat simpler
|
|
||||||
// if the cursors included the comments.
|
|
||||||
|
|
||||||
tokFile := fset.File(stmt.Pos())
|
|
||||||
lineOf := tokFile.Line
|
|
||||||
stmtStartLine, stmtEndLine := lineOf(stmt.Pos()), lineOf(stmt.End())
|
|
||||||
|
|
||||||
var from, to token.Pos
|
|
||||||
// bounds of adjacent syntax/comments on same line, if any
|
|
||||||
limits := func(left, right token.Pos) {
|
|
||||||
if lineOf(left) == stmtStartLine {
|
|
||||||
from = left
|
|
||||||
}
|
|
||||||
if lineOf(right) == stmtEndLine {
|
|
||||||
to = right
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO(pjw): there are other places a statement might be removed:
|
|
||||||
// IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] .
|
|
||||||
// (removing the blocks requires more rewriting than this routine would do)
|
|
||||||
// CommCase = "case" ( SendStmt | RecvStmt ) | "default" .
|
|
||||||
// (removing the stmt requires more rewriting, and it's unclear what the user means)
|
|
||||||
switch parent := curStmt.Parent().Node().(type) {
|
|
||||||
case *ast.SwitchStmt:
|
|
||||||
limits(parent.Switch, parent.Body.Lbrace)
|
|
||||||
case *ast.TypeSwitchStmt:
|
|
||||||
limits(parent.Switch, parent.Body.Lbrace)
|
|
||||||
if parent.Assign == stmt {
|
|
||||||
return nil // don't let the user break the type switch
|
|
||||||
}
|
|
||||||
case *ast.BlockStmt:
|
|
||||||
limits(parent.Lbrace, parent.Rbrace)
|
|
||||||
case *ast.CommClause:
|
|
||||||
limits(parent.Colon, curStmt.Parent().Parent().Node().(*ast.BlockStmt).Rbrace)
|
|
||||||
if parent.Comm == stmt {
|
|
||||||
return nil // maybe the user meant to remove the entire CommClause?
|
|
||||||
}
|
|
||||||
case *ast.CaseClause:
|
|
||||||
limits(parent.Colon, curStmt.Parent().Parent().Node().(*ast.BlockStmt).Rbrace)
|
|
||||||
case *ast.ForStmt:
|
|
||||||
limits(parent.For, parent.Body.Lbrace)
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil // not one of ours
|
|
||||||
}
|
|
||||||
|
|
||||||
if prev, found := curStmt.PrevSibling(); found && lineOf(prev.Node().End()) == stmtStartLine {
|
|
||||||
from = prev.Node().End() // preceding statement ends on same line
|
|
||||||
}
|
|
||||||
if next, found := curStmt.NextSibling(); found && lineOf(next.Node().Pos()) == stmtEndLine {
|
|
||||||
to = next.Node().Pos() // following statement begins on same line
|
|
||||||
}
|
|
||||||
// and now for the comments
|
|
||||||
Outer:
|
|
||||||
for _, cg := range enclosingFile(curStmt).Comments {
|
|
||||||
for _, co := range cg.List {
|
|
||||||
if lineOf(co.End()) < stmtStartLine {
|
|
||||||
continue
|
|
||||||
} else if lineOf(co.Pos()) > stmtEndLine {
|
|
||||||
break Outer // no more are possible
|
|
||||||
}
|
|
||||||
if lineOf(co.End()) == stmtStartLine && co.End() < stmt.Pos() {
|
|
||||||
if !from.IsValid() || co.End() > from {
|
|
||||||
from = co.End()
|
|
||||||
continue // maybe there are more
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if lineOf(co.Pos()) == stmtEndLine && co.Pos() > stmt.End() {
|
|
||||||
if !to.IsValid() || co.Pos() < to {
|
|
||||||
to = co.Pos()
|
|
||||||
continue // maybe there are more
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if either from or to is valid, just remove the statement
|
|
||||||
// otherwise remove the line
|
|
||||||
edit := analysis.TextEdit{Pos: stmt.Pos(), End: stmt.End()}
|
|
||||||
if from.IsValid() || to.IsValid() {
|
|
||||||
// remove just the statement.
|
|
||||||
// we can't tell if there is a ; or whitespace right after the statement
|
|
||||||
// ideally we'd like to remove the former and leave the latter
|
|
||||||
// (if gofmt has run, there likely won't be a ;)
|
|
||||||
// In type switches we know there's a semicolon somewhere after the statement,
|
|
||||||
// but the extra work for this special case is not worth it, as gofmt will fix it.
|
|
||||||
return []analysis.TextEdit{edit}
|
|
||||||
}
|
|
||||||
// remove the whole line
|
|
||||||
for lineOf(edit.Pos) == stmtStartLine {
|
|
||||||
edit.Pos--
|
|
||||||
}
|
|
||||||
edit.Pos++ // get back tostmtStartLine
|
|
||||||
for lineOf(edit.End) == stmtEndLine {
|
|
||||||
edit.End++
|
|
||||||
}
|
|
||||||
return []analysis.TextEdit{edit}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comments returns an iterator over the comments overlapping the specified interval.
|
|
||||||
func Comments(file *ast.File, start, end token.Pos) iter.Seq[*ast.Comment] {
|
|
||||||
// TODO(adonovan): optimize use binary O(log n) instead of linear O(n) search.
|
|
||||||
return func(yield func(*ast.Comment) bool) {
|
|
||||||
for _, cg := range file.Comments {
|
|
||||||
for _, co := range cg.List {
|
|
||||||
if co.Pos() > end {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if co.End() < start {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !yield(co) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsStdPackage reports whether the specified package path belongs to a
|
|
||||||
// package in the standard library (including internal dependencies).
|
|
||||||
func IsStdPackage(path string) bool {
|
|
||||||
// A standard package has no dot in its first segment.
|
|
||||||
// (It may yet have a dot, e.g. "vendor/golang.org/x/foo".)
|
|
||||||
slash := strings.IndexByte(path, '/')
|
|
||||||
if slash < 0 {
|
|
||||||
slash = len(path)
|
|
||||||
}
|
|
||||||
return !strings.Contains(path[:slash], ".") && path != "testdata"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Range returns an [analysis.Range] for the specified start and end positions.
|
// Range returns an [analysis.Range] for the specified start and end positions.
|
||||||
func Range(pos, end token.Pos) analysis.Range {
|
func Range(pos, end token.Pos) analysis.Range {
|
||||||
return tokenRange{pos, end}
|
return tokenRange{pos, end}
|
||||||
|
|
@ -672,9 +178,3 @@ type tokenRange struct{ StartPos, EndPos token.Pos }
|
||||||
|
|
||||||
func (r tokenRange) Pos() token.Pos { return r.StartPos }
|
func (r tokenRange) Pos() token.Pos { return r.StartPos }
|
||||||
func (r tokenRange) End() token.Pos { return r.EndPos }
|
func (r tokenRange) End() token.Pos { return r.EndPos }
|
||||||
|
|
||||||
// enclosingFile returns the syntax tree for the file enclosing c.
|
|
||||||
func enclosingFile(c inspector.Cursor) *ast.File {
|
|
||||||
c, _ = moreiters.First(c.Enclosing((*ast.File)(nil)))
|
|
||||||
return c.Node().(*ast.File)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
2
src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/extractdoc.go
generated
vendored
2
src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/extractdoc.go
generated
vendored
|
|
@ -35,7 +35,7 @@ import (
|
||||||
//
|
//
|
||||||
// var Analyzer = &analysis.Analyzer{
|
// var Analyzer = &analysis.Analyzer{
|
||||||
// Name: "halting",
|
// Name: "halting",
|
||||||
// Doc: analysisutil.MustExtractDoc(doc, "halting"),
|
// Doc: analysisinternal.MustExtractDoc(doc, "halting"),
|
||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
func MustExtractDoc(content, name string) string {
|
func MustExtractDoc(content, name string) string {
|
||||||
|
|
|
||||||
22
src/cmd/vendor/golang.org/x/tools/internal/astutil/comment.go
generated
vendored
22
src/cmd/vendor/golang.org/x/tools/internal/astutil/comment.go
generated
vendored
|
|
@ -7,6 +7,7 @@ package astutil
|
||||||
import (
|
import (
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"iter"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -111,3 +112,24 @@ func Directives(g *ast.CommentGroup) (res []*Directive) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Comments returns an iterator over the comments overlapping the specified interval.
|
||||||
|
func Comments(file *ast.File, start, end token.Pos) iter.Seq[*ast.Comment] {
|
||||||
|
// TODO(adonovan): optimize use binary O(log n) instead of linear O(n) search.
|
||||||
|
return func(yield func(*ast.Comment) bool) {
|
||||||
|
for _, cg := range file.Comments {
|
||||||
|
for _, co := range cg.List {
|
||||||
|
if co.Pos() > end {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if co.End() < start {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !yield(co) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
8
src/cmd/vendor/golang.org/x/tools/internal/astutil/equal.go
generated
vendored
8
src/cmd/vendor/golang.org/x/tools/internal/astutil/equal.go
generated
vendored
|
|
@ -26,6 +26,14 @@ func Equal(x, y ast.Node, identical func(x, y *ast.Ident) bool) bool {
|
||||||
return equal(reflect.ValueOf(x), reflect.ValueOf(y), identical)
|
return equal(reflect.ValueOf(x), reflect.ValueOf(y), identical)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EqualSyntax reports whether x and y are equal.
|
||||||
|
// Identifiers are considered equal if they are spelled the same.
|
||||||
|
// Comments are ignored.
|
||||||
|
func EqualSyntax(x, y ast.Expr) bool {
|
||||||
|
sameName := func(x, y *ast.Ident) bool { return x.Name == y.Name }
|
||||||
|
return Equal(x, y, sameName)
|
||||||
|
}
|
||||||
|
|
||||||
func equal(x, y reflect.Value, identical func(x, y *ast.Ident) bool) bool {
|
func equal(x, y reflect.Value, identical func(x, y *ast.Ident) bool) bool {
|
||||||
// Ensure types are the same
|
// Ensure types are the same
|
||||||
if x.Type() != y.Type() {
|
if x.Type() != y.Type() {
|
||||||
|
|
|
||||||
50
src/cmd/vendor/golang.org/x/tools/internal/astutil/util.go
generated
vendored
50
src/cmd/vendor/golang.org/x/tools/internal/astutil/util.go
generated
vendored
|
|
@ -6,7 +6,13 @@ package astutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
"go/printer"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/ast/edge"
|
||||||
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
|
"golang.org/x/tools/internal/moreiters"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PreorderStack traverses the tree rooted at root,
|
// PreorderStack traverses the tree rooted at root,
|
||||||
|
|
@ -67,3 +73,47 @@ func NodeContains(n ast.Node, pos token.Pos) bool {
|
||||||
}
|
}
|
||||||
return start <= pos && pos <= end
|
return start <= pos && pos <= end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsChildOf reports whether cur.ParentEdge is ek.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): promote to a method of Cursor.
|
||||||
|
func IsChildOf(cur inspector.Cursor, ek edge.Kind) bool {
|
||||||
|
got, _ := cur.ParentEdge()
|
||||||
|
return got == ek
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnclosingFile returns the syntax tree for the file enclosing c.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): promote this to a method of Cursor.
|
||||||
|
func EnclosingFile(c inspector.Cursor) *ast.File {
|
||||||
|
c, _ = moreiters.First(c.Enclosing((*ast.File)(nil)))
|
||||||
|
return c.Node().(*ast.File)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DocComment returns the doc comment for a node, if any.
|
||||||
|
func DocComment(n ast.Node) *ast.CommentGroup {
|
||||||
|
switch n := n.(type) {
|
||||||
|
case *ast.FuncDecl:
|
||||||
|
return n.Doc
|
||||||
|
case *ast.GenDecl:
|
||||||
|
return n.Doc
|
||||||
|
case *ast.ValueSpec:
|
||||||
|
return n.Doc
|
||||||
|
case *ast.TypeSpec:
|
||||||
|
return n.Doc
|
||||||
|
case *ast.File:
|
||||||
|
return n.Doc
|
||||||
|
case *ast.ImportSpec:
|
||||||
|
return n.Doc
|
||||||
|
case *ast.Field:
|
||||||
|
return n.Doc
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format returns a string representation of the node n.
|
||||||
|
func Format(fset *token.FileSet, n ast.Node) string {
|
||||||
|
var buf strings.Builder
|
||||||
|
printer.Fprint(&buf, fset, n) // ignore errors
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
|
||||||
5
src/cmd/vendor/golang.org/x/tools/internal/diff/lcs/old.go
generated
vendored
5
src/cmd/vendor/golang.org/x/tools/internal/diff/lcs/old.go
generated
vendored
|
|
@ -378,10 +378,7 @@ func (e *editGraph) twoDone(df, db int) (int, bool) {
|
||||||
return 0, false // diagonals cannot overlap
|
return 0, false // diagonals cannot overlap
|
||||||
}
|
}
|
||||||
kmin := max(-df, -db+e.delta)
|
kmin := max(-df, -db+e.delta)
|
||||||
kmax := db + e.delta
|
kmax := min(df, db+e.delta)
|
||||||
if df < kmax {
|
|
||||||
kmax = df
|
|
||||||
}
|
|
||||||
for k := kmin; k <= kmax; k += 2 {
|
for k := kmin; k <= kmax; k += 2 {
|
||||||
x := e.vf.get(df, k)
|
x := e.vf.get(df, k)
|
||||||
u := e.vb.get(db, k-e.delta)
|
u := e.vb.get(db, k-e.delta)
|
||||||
|
|
|
||||||
8
src/cmd/vendor/golang.org/x/tools/internal/diff/lcs/sequence.go
generated
vendored
8
src/cmd/vendor/golang.org/x/tools/internal/diff/lcs/sequence.go
generated
vendored
|
|
@ -103,11 +103,3 @@ func commonSuffixLenString(a, b string) int {
|
||||||
}
|
}
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func min(x, y int) int {
|
|
||||||
if x < y {
|
|
||||||
return x
|
|
||||||
} else {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
49
src/cmd/vendor/golang.org/x/tools/internal/packagepath/packagepath.go
generated
vendored
Normal file
49
src/cmd/vendor/golang.org/x/tools/internal/packagepath/packagepath.go
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
// 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 packagepath provides metadata operations on package path
|
||||||
|
// strings.
|
||||||
|
package packagepath
|
||||||
|
|
||||||
|
// (This package should not depend on go/ast.)
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// CanImport reports whether one package is allowed to import another.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): allow customization of the accessibility relation
|
||||||
|
// (e.g. for Bazel).
|
||||||
|
func CanImport(from, to string) bool {
|
||||||
|
// TODO(adonovan): better segment hygiene.
|
||||||
|
if to == "internal" || strings.HasPrefix(to, "internal/") {
|
||||||
|
// Special case: only std packages may import internal/...
|
||||||
|
// We can't reliably know whether we're in std, so we
|
||||||
|
// use a heuristic on the first segment.
|
||||||
|
first, _, _ := strings.Cut(from, "/")
|
||||||
|
if strings.Contains(first, ".") {
|
||||||
|
return false // example.com/foo ∉ std
|
||||||
|
}
|
||||||
|
if first == "testdata" {
|
||||||
|
return false // testdata/foo ∉ std
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(to, "/internal") {
|
||||||
|
return strings.HasPrefix(from, to[:len(to)-len("/internal")])
|
||||||
|
}
|
||||||
|
if i := strings.LastIndex(to, "/internal/"); i >= 0 {
|
||||||
|
return strings.HasPrefix(from, to[:i])
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsStdPackage reports whether the specified package path belongs to a
|
||||||
|
// package in the standard library (including internal dependencies).
|
||||||
|
func IsStdPackage(path string) bool {
|
||||||
|
// A standard package has no dot in its first segment.
|
||||||
|
// (It may yet have a dot, e.g. "vendor/golang.org/x/foo".)
|
||||||
|
slash := strings.IndexByte(path, '/')
|
||||||
|
if slash < 0 {
|
||||||
|
slash = len(path)
|
||||||
|
}
|
||||||
|
return !strings.Contains(path[:slash], ".") && path != "testdata"
|
||||||
|
}
|
||||||
484
src/cmd/vendor/golang.org/x/tools/internal/refactor/delete.go
generated
vendored
Normal file
484
src/cmd/vendor/golang.org/x/tools/internal/refactor/delete.go
generated
vendored
Normal file
|
|
@ -0,0 +1,484 @@
|
||||||
|
// 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 refactor
|
||||||
|
|
||||||
|
// This file defines operations for computing deletion edits.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
"golang.org/x/tools/go/ast/edge"
|
||||||
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
|
"golang.org/x/tools/internal/astutil"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
|
"golang.org/x/tools/internal/typesinternal/typeindex"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteVar returns edits to delete the declaration of a variable or
|
||||||
|
// constant whose defining identifier is curId.
|
||||||
|
//
|
||||||
|
// It handles variants including:
|
||||||
|
// - GenDecl > ValueSpec versus AssignStmt;
|
||||||
|
// - RHS expression has effects, or not;
|
||||||
|
// - entire statement/declaration may be eliminated;
|
||||||
|
// and removes associated comments.
|
||||||
|
//
|
||||||
|
// If it cannot make the necessary edits, such as for a function
|
||||||
|
// parameter or result, it returns nil.
|
||||||
|
func DeleteVar(tokFile *token.File, info *types.Info, curId inspector.Cursor) []analysis.TextEdit {
|
||||||
|
switch ek, _ := curId.ParentEdge(); ek {
|
||||||
|
case edge.ValueSpec_Names:
|
||||||
|
return deleteVarFromValueSpec(tokFile, info, curId)
|
||||||
|
|
||||||
|
case edge.AssignStmt_Lhs:
|
||||||
|
return deleteVarFromAssignStmt(tokFile, info, curId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// e.g. function receiver, parameter, or result,
|
||||||
|
// or "switch v := expr.(T) {}" (which has no object).
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// deleteVarFromValueSpec returns edits to delete the declaration of a
|
||||||
|
// variable or constant within a ValueSpec.
|
||||||
|
//
|
||||||
|
// Precondition: curId is Ident beneath ValueSpec.Names beneath GenDecl.
|
||||||
|
//
|
||||||
|
// See also [deleteVarFromAssignStmt], which has parallel structure.
|
||||||
|
func deleteVarFromValueSpec(tokFile *token.File, info *types.Info, curIdent inspector.Cursor) []analysis.TextEdit {
|
||||||
|
var (
|
||||||
|
id = curIdent.Node().(*ast.Ident)
|
||||||
|
curSpec = curIdent.Parent()
|
||||||
|
spec = curSpec.Node().(*ast.ValueSpec)
|
||||||
|
)
|
||||||
|
|
||||||
|
declaresOtherNames := slices.ContainsFunc(spec.Names, func(name *ast.Ident) bool {
|
||||||
|
return name != id && name.Name != "_"
|
||||||
|
})
|
||||||
|
noRHSEffects := !slices.ContainsFunc(spec.Values, func(rhs ast.Expr) bool {
|
||||||
|
return !typesinternal.NoEffects(info, rhs)
|
||||||
|
})
|
||||||
|
if !declaresOtherNames && noRHSEffects {
|
||||||
|
// The spec is no longer needed, either to declare
|
||||||
|
// other variables, or for its side effects.
|
||||||
|
return DeleteSpec(tokFile, curSpec)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The spec is still needed, either for
|
||||||
|
// at least one LHS, or for effects on RHS.
|
||||||
|
// Blank out or delete just one LHS.
|
||||||
|
|
||||||
|
_, index := curIdent.ParentEdge() // index of LHS within ValueSpec.Names
|
||||||
|
|
||||||
|
// If there is no RHS, we can delete the LHS.
|
||||||
|
if len(spec.Values) == 0 {
|
||||||
|
var pos, end token.Pos
|
||||||
|
if index == len(spec.Names)-1 {
|
||||||
|
// Delete final name.
|
||||||
|
//
|
||||||
|
// var _, lhs1 T
|
||||||
|
// ------
|
||||||
|
pos = spec.Names[index-1].End()
|
||||||
|
end = spec.Names[index].End()
|
||||||
|
} else {
|
||||||
|
// Delete non-final name.
|
||||||
|
//
|
||||||
|
// var lhs0, _ T
|
||||||
|
// ------
|
||||||
|
pos = spec.Names[index].Pos()
|
||||||
|
end = spec.Names[index+1].Pos()
|
||||||
|
}
|
||||||
|
return []analysis.TextEdit{{
|
||||||
|
Pos: pos,
|
||||||
|
End: end,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the assignment is n:n and the RHS has no effects,
|
||||||
|
// we can delete the LHS and its corresponding RHS.
|
||||||
|
if len(spec.Names) == len(spec.Values) &&
|
||||||
|
typesinternal.NoEffects(info, spec.Values[index]) {
|
||||||
|
|
||||||
|
if index == len(spec.Names)-1 {
|
||||||
|
// Delete final items.
|
||||||
|
//
|
||||||
|
// var _, lhs1 = rhs0, rhs1
|
||||||
|
// ------ ------
|
||||||
|
return []analysis.TextEdit{
|
||||||
|
{
|
||||||
|
Pos: spec.Names[index-1].End(),
|
||||||
|
End: spec.Names[index].End(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Pos: spec.Values[index-1].End(),
|
||||||
|
End: spec.Values[index].End(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Delete non-final items.
|
||||||
|
//
|
||||||
|
// var lhs0, _ = rhs0, rhs1
|
||||||
|
// ------ ------
|
||||||
|
return []analysis.TextEdit{
|
||||||
|
{
|
||||||
|
Pos: spec.Names[index].Pos(),
|
||||||
|
End: spec.Names[index+1].Pos(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Pos: spec.Values[index].Pos(),
|
||||||
|
End: spec.Values[index+1].Pos(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We cannot delete the RHS.
|
||||||
|
// Blank out the LHS.
|
||||||
|
return []analysis.TextEdit{{
|
||||||
|
Pos: id.Pos(),
|
||||||
|
End: id.End(),
|
||||||
|
NewText: []byte("_"),
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Precondition: curId is Ident beneath AssignStmt.Lhs.
|
||||||
|
//
|
||||||
|
// See also [deleteVarFromValueSpec], which has parallel structure.
|
||||||
|
func deleteVarFromAssignStmt(tokFile *token.File, info *types.Info, curIdent inspector.Cursor) []analysis.TextEdit {
|
||||||
|
var (
|
||||||
|
id = curIdent.Node().(*ast.Ident)
|
||||||
|
curStmt = curIdent.Parent()
|
||||||
|
assign = curStmt.Node().(*ast.AssignStmt)
|
||||||
|
)
|
||||||
|
|
||||||
|
declaresOtherNames := slices.ContainsFunc(assign.Lhs, func(lhs ast.Expr) bool {
|
||||||
|
lhsId, ok := lhs.(*ast.Ident)
|
||||||
|
return ok && lhsId != id && lhsId.Name != "_"
|
||||||
|
})
|
||||||
|
noRHSEffects := !slices.ContainsFunc(assign.Rhs, func(rhs ast.Expr) bool {
|
||||||
|
return !typesinternal.NoEffects(info, rhs)
|
||||||
|
})
|
||||||
|
if !declaresOtherNames && noRHSEffects {
|
||||||
|
// The assignment is no longer needed, either to
|
||||||
|
// declare other variables, or for its side effects.
|
||||||
|
if edits := DeleteStmt(tokFile, curStmt); edits != nil {
|
||||||
|
return edits
|
||||||
|
}
|
||||||
|
// Statement could not not be deleted in this context.
|
||||||
|
// Fall back to conservative deletion.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The assign is still needed, either for
|
||||||
|
// at least one LHS, or for effects on RHS,
|
||||||
|
// or because it cannot deleted because of its context.
|
||||||
|
// Blank out or delete just one LHS.
|
||||||
|
|
||||||
|
// If the assignment is 1:1 and the RHS has no effects,
|
||||||
|
// we can delete the LHS and its corresponding RHS.
|
||||||
|
_, index := curIdent.ParentEdge()
|
||||||
|
if len(assign.Lhs) > 1 &&
|
||||||
|
len(assign.Lhs) == len(assign.Rhs) &&
|
||||||
|
typesinternal.NoEffects(info, assign.Rhs[index]) {
|
||||||
|
|
||||||
|
if index == len(assign.Lhs)-1 {
|
||||||
|
// Delete final items.
|
||||||
|
//
|
||||||
|
// _, lhs1 := rhs0, rhs1
|
||||||
|
// ------ ------
|
||||||
|
return []analysis.TextEdit{
|
||||||
|
{
|
||||||
|
Pos: assign.Lhs[index-1].End(),
|
||||||
|
End: assign.Lhs[index].End(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Pos: assign.Rhs[index-1].End(),
|
||||||
|
End: assign.Rhs[index].End(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Delete non-final items.
|
||||||
|
//
|
||||||
|
// lhs0, _ := rhs0, rhs1
|
||||||
|
// ------ ------
|
||||||
|
return []analysis.TextEdit{
|
||||||
|
{
|
||||||
|
Pos: assign.Lhs[index].Pos(),
|
||||||
|
End: assign.Lhs[index+1].Pos(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Pos: assign.Rhs[index].Pos(),
|
||||||
|
End: assign.Rhs[index+1].Pos(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We cannot delete the RHS.
|
||||||
|
// Blank out the LHS.
|
||||||
|
edits := []analysis.TextEdit{{
|
||||||
|
Pos: id.Pos(),
|
||||||
|
End: id.End(),
|
||||||
|
NewText: []byte("_"),
|
||||||
|
}}
|
||||||
|
|
||||||
|
// If this eliminates the final variable declared by
|
||||||
|
// an := statement, we need to turn it into an =
|
||||||
|
// assignment to avoid a "no new variables on left
|
||||||
|
// side of :=" error.
|
||||||
|
if !declaresOtherNames {
|
||||||
|
edits = append(edits, analysis.TextEdit{
|
||||||
|
Pos: assign.TokPos,
|
||||||
|
End: assign.TokPos + token.Pos(len(":=")),
|
||||||
|
NewText: []byte("="),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return edits
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteSpec returns edits to delete the {Type,Value}Spec identified by curSpec.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): add test suite. Test for consts as well.
|
||||||
|
func DeleteSpec(tokFile *token.File, curSpec inspector.Cursor) []analysis.TextEdit {
|
||||||
|
var (
|
||||||
|
spec = curSpec.Node().(ast.Spec)
|
||||||
|
curDecl = curSpec.Parent()
|
||||||
|
decl = curDecl.Node().(*ast.GenDecl)
|
||||||
|
)
|
||||||
|
|
||||||
|
// If it is the sole spec in the decl,
|
||||||
|
// delete the entire decl.
|
||||||
|
if len(decl.Specs) == 1 {
|
||||||
|
return DeleteDecl(tokFile, curDecl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the spec and its comments.
|
||||||
|
_, index := curSpec.ParentEdge() // index of ValueSpec within GenDecl.Specs
|
||||||
|
pos, end := spec.Pos(), spec.End()
|
||||||
|
if doc := astutil.DocComment(spec); doc != nil {
|
||||||
|
pos = doc.Pos() // leading comment
|
||||||
|
}
|
||||||
|
if index == len(decl.Specs)-1 {
|
||||||
|
// Delete final spec.
|
||||||
|
if c := eolComment(spec); c != nil {
|
||||||
|
// var (v int // comment \n)
|
||||||
|
end = c.End()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Delete non-final spec.
|
||||||
|
// var ( a T; b T )
|
||||||
|
// -----
|
||||||
|
end = decl.Specs[index+1].Pos()
|
||||||
|
}
|
||||||
|
return []analysis.TextEdit{{
|
||||||
|
Pos: pos,
|
||||||
|
End: end,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteDecl returns edits to delete the ast.Decl identified by curDecl.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): add test suite.
|
||||||
|
func DeleteDecl(tokFile *token.File, curDecl inspector.Cursor) []analysis.TextEdit {
|
||||||
|
decl := curDecl.Node().(ast.Decl)
|
||||||
|
|
||||||
|
ek, _ := curDecl.ParentEdge()
|
||||||
|
switch ek {
|
||||||
|
case edge.DeclStmt_Decl:
|
||||||
|
return DeleteStmt(tokFile, curDecl.Parent())
|
||||||
|
|
||||||
|
case edge.File_Decls:
|
||||||
|
pos, end := decl.Pos(), decl.End()
|
||||||
|
if doc := astutil.DocComment(decl); doc != nil {
|
||||||
|
pos = doc.Pos()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete free-floating comments on same line as rparen.
|
||||||
|
// var (...) // comment
|
||||||
|
var (
|
||||||
|
file = curDecl.Parent().Node().(*ast.File)
|
||||||
|
lineOf = tokFile.Line
|
||||||
|
declEndLine = lineOf(decl.End())
|
||||||
|
)
|
||||||
|
for _, cg := range file.Comments {
|
||||||
|
for _, c := range cg.List {
|
||||||
|
if c.Pos() < end {
|
||||||
|
continue // too early
|
||||||
|
}
|
||||||
|
commentEndLine := lineOf(c.End())
|
||||||
|
if commentEndLine > declEndLine {
|
||||||
|
break // too late
|
||||||
|
} else if lineOf(c.Pos()) == declEndLine && commentEndLine == declEndLine {
|
||||||
|
end = c.End()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return []analysis.TextEdit{{
|
||||||
|
Pos: pos,
|
||||||
|
End: end,
|
||||||
|
}}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Decl parent is %v, want DeclStmt or File", ek))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteStmt returns the edits to remove the [ast.Stmt] identified by
|
||||||
|
// curStmt, if it is contained within a BlockStmt, CaseClause,
|
||||||
|
// CommClause, or is the STMT in switch STMT; ... {...}. It returns nil otherwise.
|
||||||
|
func DeleteStmt(tokFile *token.File, curStmt inspector.Cursor) []analysis.TextEdit {
|
||||||
|
stmt := curStmt.Node().(ast.Stmt)
|
||||||
|
// if the stmt is on a line by itself delete the whole line
|
||||||
|
// otherwise just delete the statement.
|
||||||
|
|
||||||
|
// this logic would be a lot simpler with the file contents, and somewhat simpler
|
||||||
|
// if the cursors included the comments.
|
||||||
|
|
||||||
|
lineOf := tokFile.Line
|
||||||
|
stmtStartLine, stmtEndLine := lineOf(stmt.Pos()), lineOf(stmt.End())
|
||||||
|
|
||||||
|
var from, to token.Pos
|
||||||
|
// bounds of adjacent syntax/comments on same line, if any
|
||||||
|
limits := func(left, right token.Pos) {
|
||||||
|
if lineOf(left) == stmtStartLine {
|
||||||
|
from = left
|
||||||
|
}
|
||||||
|
if lineOf(right) == stmtEndLine {
|
||||||
|
to = right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO(pjw): there are other places a statement might be removed:
|
||||||
|
// IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] .
|
||||||
|
// (removing the blocks requires more rewriting than this routine would do)
|
||||||
|
// CommCase = "case" ( SendStmt | RecvStmt ) | "default" .
|
||||||
|
// (removing the stmt requires more rewriting, and it's unclear what the user means)
|
||||||
|
switch parent := curStmt.Parent().Node().(type) {
|
||||||
|
case *ast.SwitchStmt:
|
||||||
|
limits(parent.Switch, parent.Body.Lbrace)
|
||||||
|
case *ast.TypeSwitchStmt:
|
||||||
|
limits(parent.Switch, parent.Body.Lbrace)
|
||||||
|
if parent.Assign == stmt {
|
||||||
|
return nil // don't let the user break the type switch
|
||||||
|
}
|
||||||
|
case *ast.BlockStmt:
|
||||||
|
limits(parent.Lbrace, parent.Rbrace)
|
||||||
|
case *ast.CommClause:
|
||||||
|
limits(parent.Colon, curStmt.Parent().Parent().Node().(*ast.BlockStmt).Rbrace)
|
||||||
|
if parent.Comm == stmt {
|
||||||
|
return nil // maybe the user meant to remove the entire CommClause?
|
||||||
|
}
|
||||||
|
case *ast.CaseClause:
|
||||||
|
limits(parent.Colon, curStmt.Parent().Parent().Node().(*ast.BlockStmt).Rbrace)
|
||||||
|
case *ast.ForStmt:
|
||||||
|
limits(parent.For, parent.Body.Lbrace)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil // not one of ours
|
||||||
|
}
|
||||||
|
|
||||||
|
if prev, found := curStmt.PrevSibling(); found && lineOf(prev.Node().End()) == stmtStartLine {
|
||||||
|
from = prev.Node().End() // preceding statement ends on same line
|
||||||
|
}
|
||||||
|
if next, found := curStmt.NextSibling(); found && lineOf(next.Node().Pos()) == stmtEndLine {
|
||||||
|
to = next.Node().Pos() // following statement begins on same line
|
||||||
|
}
|
||||||
|
// and now for the comments
|
||||||
|
Outer:
|
||||||
|
for _, cg := range astutil.EnclosingFile(curStmt).Comments {
|
||||||
|
for _, co := range cg.List {
|
||||||
|
if lineOf(co.End()) < stmtStartLine {
|
||||||
|
continue
|
||||||
|
} else if lineOf(co.Pos()) > stmtEndLine {
|
||||||
|
break Outer // no more are possible
|
||||||
|
}
|
||||||
|
if lineOf(co.End()) == stmtStartLine && co.End() < stmt.Pos() {
|
||||||
|
if !from.IsValid() || co.End() > from {
|
||||||
|
from = co.End()
|
||||||
|
continue // maybe there are more
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if lineOf(co.Pos()) == stmtEndLine && co.Pos() > stmt.End() {
|
||||||
|
if !to.IsValid() || co.Pos() < to {
|
||||||
|
to = co.Pos()
|
||||||
|
continue // maybe there are more
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if either from or to is valid, just remove the statement
|
||||||
|
// otherwise remove the line
|
||||||
|
edit := analysis.TextEdit{Pos: stmt.Pos(), End: stmt.End()}
|
||||||
|
if from.IsValid() || to.IsValid() {
|
||||||
|
// remove just the statement.
|
||||||
|
// we can't tell if there is a ; or whitespace right after the statement
|
||||||
|
// ideally we'd like to remove the former and leave the latter
|
||||||
|
// (if gofmt has run, there likely won't be a ;)
|
||||||
|
// In type switches we know there's a semicolon somewhere after the statement,
|
||||||
|
// but the extra work for this special case is not worth it, as gofmt will fix it.
|
||||||
|
return []analysis.TextEdit{edit}
|
||||||
|
}
|
||||||
|
// remove the whole line
|
||||||
|
for lineOf(edit.Pos) == stmtStartLine {
|
||||||
|
edit.Pos--
|
||||||
|
}
|
||||||
|
edit.Pos++ // get back tostmtStartLine
|
||||||
|
for lineOf(edit.End) == stmtEndLine {
|
||||||
|
edit.End++
|
||||||
|
}
|
||||||
|
return []analysis.TextEdit{edit}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteUnusedVars computes the edits required to delete the
|
||||||
|
// declarations of any local variables whose last uses are in the
|
||||||
|
// curDelend subtree, which is about to be deleted.
|
||||||
|
func DeleteUnusedVars(index *typeindex.Index, info *types.Info, tokFile *token.File, curDelend inspector.Cursor) []analysis.TextEdit {
|
||||||
|
// TODO(adonovan): we might want to generalize this by
|
||||||
|
// splitting the two phases below, so that we can gather
|
||||||
|
// across a whole sequence of deletions then finally compute the
|
||||||
|
// set of variables that are no longer wanted.
|
||||||
|
|
||||||
|
// Count number of deletions of each var.
|
||||||
|
delcount := make(map[*types.Var]int)
|
||||||
|
for curId := range curDelend.Preorder((*ast.Ident)(nil)) {
|
||||||
|
id := curId.Node().(*ast.Ident)
|
||||||
|
if v, ok := info.Uses[id].(*types.Var); ok &&
|
||||||
|
typesinternal.GetVarKind(v) == typesinternal.LocalVar { // always false before go1.25
|
||||||
|
delcount[v]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete declaration of each var that became unused.
|
||||||
|
var edits []analysis.TextEdit
|
||||||
|
for v, count := range delcount {
|
||||||
|
if len(slices.Collect(index.Uses(v))) == count {
|
||||||
|
if curDefId, ok := index.Def(v); ok {
|
||||||
|
edits = append(edits, DeleteVar(tokFile, info, curDefId)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return edits
|
||||||
|
}
|
||||||
|
|
||||||
|
func eolComment(n ast.Node) *ast.CommentGroup {
|
||||||
|
// TODO(adonovan): support:
|
||||||
|
// func f() {...} // comment
|
||||||
|
switch n := n.(type) {
|
||||||
|
case *ast.GenDecl:
|
||||||
|
if !n.TokPos.IsValid() && len(n.Specs) == 1 {
|
||||||
|
return eolComment(n.Specs[0])
|
||||||
|
}
|
||||||
|
case *ast.ValueSpec:
|
||||||
|
return n.Comment
|
||||||
|
case *ast.TypeSpec:
|
||||||
|
return n.Comment
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
127
src/cmd/vendor/golang.org/x/tools/internal/refactor/imports.go
generated
vendored
Normal file
127
src/cmd/vendor/golang.org/x/tools/internal/refactor/imports.go
generated
vendored
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
// 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 refactor
|
||||||
|
|
||||||
|
// This file defines operations for computing edits to imports.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
pathpkg "path"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
"golang.org/x/tools/internal/packagepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddImport returns the prefix (either "pkg." or "") that should be
|
||||||
|
// used to qualify references to the desired symbol (member) imported
|
||||||
|
// from the specified package, plus any necessary edits to the file's
|
||||||
|
// import declaration to add a new import.
|
||||||
|
//
|
||||||
|
// If the import already exists, and is accessible at pos, AddImport
|
||||||
|
// returns the existing name and no edits. (If the existing import is
|
||||||
|
// a dot import, the prefix is "".)
|
||||||
|
//
|
||||||
|
// Otherwise, it adds a new import, using a local name derived from
|
||||||
|
// the preferred name. To request a blank import, use a preferredName
|
||||||
|
// of "_", and discard the prefix result; member is ignored in this
|
||||||
|
// case.
|
||||||
|
//
|
||||||
|
// AddImport accepts the caller's implicit claim that the imported
|
||||||
|
// package declares member.
|
||||||
|
//
|
||||||
|
// AddImport does not mutate its arguments.
|
||||||
|
func AddImport(info *types.Info, file *ast.File, preferredName, pkgpath, member string, pos token.Pos) (prefix string, edits []analysis.TextEdit) {
|
||||||
|
// Find innermost enclosing lexical block.
|
||||||
|
scope := info.Scopes[file].Innermost(pos)
|
||||||
|
if scope == nil {
|
||||||
|
panic("no enclosing lexical block")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is there an existing import of this package?
|
||||||
|
// If so, are we in its scope? (not shadowed)
|
||||||
|
for _, spec := range file.Imports {
|
||||||
|
pkgname := info.PkgNameOf(spec)
|
||||||
|
if pkgname != nil && pkgname.Imported().Path() == pkgpath {
|
||||||
|
name := pkgname.Name()
|
||||||
|
if preferredName == "_" {
|
||||||
|
// Request for blank import; any existing import will do.
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
if name == "." {
|
||||||
|
// The scope of ident must be the file scope.
|
||||||
|
if s, _ := scope.LookupParent(member, pos); s == info.Scopes[file] {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
} else if _, obj := scope.LookupParent(name, pos); obj == pkgname {
|
||||||
|
return name + ".", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must add a new import.
|
||||||
|
|
||||||
|
// Ensure we have a fresh name.
|
||||||
|
newName := preferredName
|
||||||
|
if preferredName != "_" {
|
||||||
|
newName = FreshName(scope, pos, preferredName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new import declaration either before the first existing
|
||||||
|
// declaration (which must exist), including its comments; or
|
||||||
|
// inside the declaration, if it is an import group.
|
||||||
|
//
|
||||||
|
// Use a renaming import whenever the preferred name is not
|
||||||
|
// available, or the chosen name does not match the last
|
||||||
|
// segment of its path.
|
||||||
|
newText := fmt.Sprintf("%q", pkgpath)
|
||||||
|
if newName != preferredName || newName != pathpkg.Base(pkgpath) {
|
||||||
|
newText = fmt.Sprintf("%s %q", newName, pkgpath)
|
||||||
|
}
|
||||||
|
|
||||||
|
decl0 := file.Decls[0]
|
||||||
|
var before ast.Node = decl0
|
||||||
|
switch decl0 := decl0.(type) {
|
||||||
|
case *ast.GenDecl:
|
||||||
|
if decl0.Doc != nil {
|
||||||
|
before = decl0.Doc
|
||||||
|
}
|
||||||
|
case *ast.FuncDecl:
|
||||||
|
if decl0.Doc != nil {
|
||||||
|
before = decl0.Doc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if gd, ok := before.(*ast.GenDecl); ok && gd.Tok == token.IMPORT && gd.Rparen.IsValid() {
|
||||||
|
// Have existing grouped import ( ... ) decl.
|
||||||
|
if packagepath.IsStdPackage(pkgpath) && len(gd.Specs) > 0 {
|
||||||
|
// Add spec for a std package before
|
||||||
|
// first existing spec, followed by
|
||||||
|
// a blank line if the next one is non-std.
|
||||||
|
first := gd.Specs[0].(*ast.ImportSpec)
|
||||||
|
pos = first.Pos()
|
||||||
|
if !packagepath.IsStdPackage(first.Path.Value) {
|
||||||
|
newText += "\n"
|
||||||
|
}
|
||||||
|
newText += "\n\t"
|
||||||
|
} else {
|
||||||
|
// Add spec at end of group.
|
||||||
|
pos = gd.Rparen
|
||||||
|
newText = "\t" + newText + "\n"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No import decl, or non-grouped import.
|
||||||
|
// Add a new import decl before first decl.
|
||||||
|
// (gofmt will merge multiple import decls.)
|
||||||
|
pos = before.Pos()
|
||||||
|
newText = "import " + newText + "\n\n"
|
||||||
|
}
|
||||||
|
return newName + ".", []analysis.TextEdit{{
|
||||||
|
Pos: pos,
|
||||||
|
End: pos,
|
||||||
|
NewText: []byte(newText),
|
||||||
|
}}
|
||||||
|
}
|
||||||
29
src/cmd/vendor/golang.org/x/tools/internal/refactor/refactor.go
generated
vendored
Normal file
29
src/cmd/vendor/golang.org/x/tools/internal/refactor/refactor.go
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// 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 refactor provides operators to compute common textual edits
|
||||||
|
// for refactoring tools.
|
||||||
|
//
|
||||||
|
// This package should not use features of the analysis API
|
||||||
|
// other than [analysis.TextEdit].
|
||||||
|
package refactor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FreshName returns the name of an identifier that is undefined
|
||||||
|
// at the specified position, based on the preferred name.
|
||||||
|
func FreshName(scope *types.Scope, pos token.Pos, preferred string) string {
|
||||||
|
newName := preferred
|
||||||
|
for i := 0; ; i++ {
|
||||||
|
if _, obj := scope.LookupParent(newName, pos); obj == nil {
|
||||||
|
break // fresh
|
||||||
|
}
|
||||||
|
newName = fmt.Sprintf("%s%d", preferred, i)
|
||||||
|
}
|
||||||
|
return newName
|
||||||
|
}
|
||||||
88
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/fx.go
generated
vendored
Normal file
88
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/fx.go
generated
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
// 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 typesinternal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NoEffects reports whether the expression has no side effects, i.e., it
|
||||||
|
// does not modify the memory state. This function is conservative: it may
|
||||||
|
// return false even when the expression has no effect.
|
||||||
|
func NoEffects(info *types.Info, expr ast.Expr) bool {
|
||||||
|
noEffects := true
|
||||||
|
ast.Inspect(expr, func(n ast.Node) bool {
|
||||||
|
switch v := n.(type) {
|
||||||
|
case nil, *ast.Ident, *ast.BasicLit, *ast.BinaryExpr, *ast.ParenExpr,
|
||||||
|
*ast.SelectorExpr, *ast.IndexExpr, *ast.SliceExpr, *ast.TypeAssertExpr,
|
||||||
|
*ast.StarExpr, *ast.CompositeLit,
|
||||||
|
// non-expressions that may appear within expressions
|
||||||
|
*ast.KeyValueExpr,
|
||||||
|
*ast.FieldList,
|
||||||
|
*ast.Field,
|
||||||
|
*ast.Ellipsis,
|
||||||
|
*ast.IndexListExpr:
|
||||||
|
// No effect.
|
||||||
|
|
||||||
|
case *ast.ArrayType,
|
||||||
|
*ast.StructType,
|
||||||
|
*ast.ChanType,
|
||||||
|
*ast.FuncType,
|
||||||
|
*ast.MapType,
|
||||||
|
*ast.InterfaceType:
|
||||||
|
// Type syntax: no effects, recursively.
|
||||||
|
// Prune descent.
|
||||||
|
return false
|
||||||
|
|
||||||
|
case *ast.UnaryExpr:
|
||||||
|
// Channel send <-ch has effects.
|
||||||
|
if v.Op == token.ARROW {
|
||||||
|
noEffects = false
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.CallExpr:
|
||||||
|
// Type conversion has no effects.
|
||||||
|
if !info.Types[v.Fun].IsType() {
|
||||||
|
if CallsPureBuiltin(info, v) {
|
||||||
|
// A call such as len(e) has no effects of its
|
||||||
|
// own, though the subexpression e might.
|
||||||
|
} else {
|
||||||
|
noEffects = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *ast.FuncLit:
|
||||||
|
// A FuncLit has no effects, but do not descend into it.
|
||||||
|
return false
|
||||||
|
|
||||||
|
default:
|
||||||
|
// All other expressions have effects
|
||||||
|
noEffects = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return noEffects
|
||||||
|
})
|
||||||
|
return noEffects
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallsPureBuiltin reports whether call is a call of a built-in
|
||||||
|
// function that is a pure computation over its operands (analogous to
|
||||||
|
// a + operator). Because it does not depend on program state, it may
|
||||||
|
// be evaluated at any point--though not necessarily at multiple
|
||||||
|
// points (consider new, make).
|
||||||
|
func CallsPureBuiltin(info *types.Info, call *ast.CallExpr) bool {
|
||||||
|
if id, ok := ast.Unparen(call.Fun).(*ast.Ident); ok {
|
||||||
|
if b, ok := info.ObjectOf(id).(*types.Builtin); ok {
|
||||||
|
switch b.Name() {
|
||||||
|
case "len", "cap", "complex", "imag", "real", "make", "new", "max", "min":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// Not: append clear close copy delete panic print println recover
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
71
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/isnamed.go
generated
vendored
Normal file
71
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/isnamed.go
generated
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
// 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 typesinternal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
"slices"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsTypeNamed reports whether t is (or is an alias for) a
|
||||||
|
// package-level defined type with the given package path and one of
|
||||||
|
// the given names. It returns false if t is nil.
|
||||||
|
//
|
||||||
|
// This function avoids allocating the concatenation of "pkg.Name",
|
||||||
|
// which is important for the performance of syntax matching.
|
||||||
|
func IsTypeNamed(t types.Type, pkgPath string, names ...string) bool {
|
||||||
|
if named, ok := types.Unalias(t).(*types.Named); ok {
|
||||||
|
tname := named.Obj()
|
||||||
|
return tname != nil &&
|
||||||
|
IsPackageLevel(tname) &&
|
||||||
|
tname.Pkg().Path() == pkgPath &&
|
||||||
|
slices.Contains(names, tname.Name())
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsPointerToNamed reports whether t is (or is an alias for) a pointer to a
|
||||||
|
// package-level defined type with the given package path and one of the given
|
||||||
|
// names. It returns false if t is not a pointer type.
|
||||||
|
func IsPointerToNamed(t types.Type, pkgPath string, names ...string) bool {
|
||||||
|
r := Unpointer(t)
|
||||||
|
if r == t {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return IsTypeNamed(r, pkgPath, names...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFunctionNamed reports whether obj is a package-level function
|
||||||
|
// defined in the given package and has one of the given names.
|
||||||
|
// It returns false if obj is nil.
|
||||||
|
//
|
||||||
|
// This function avoids allocating the concatenation of "pkg.Name",
|
||||||
|
// which is important for the performance of syntax matching.
|
||||||
|
func IsFunctionNamed(obj types.Object, pkgPath string, names ...string) bool {
|
||||||
|
f, ok := obj.(*types.Func)
|
||||||
|
return ok &&
|
||||||
|
IsPackageLevel(obj) &&
|
||||||
|
f.Pkg().Path() == pkgPath &&
|
||||||
|
f.Type().(*types.Signature).Recv() == nil &&
|
||||||
|
slices.Contains(names, f.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMethodNamed reports whether obj is a method defined on a
|
||||||
|
// package-level type with the given package and type name, and has
|
||||||
|
// one of the given names. It returns false if obj is nil.
|
||||||
|
//
|
||||||
|
// This function avoids allocating the concatenation of "pkg.TypeName.Name",
|
||||||
|
// which is important for the performance of syntax matching.
|
||||||
|
func IsMethodNamed(obj types.Object, pkgPath string, typeName string, names ...string) bool {
|
||||||
|
if fn, ok := obj.(*types.Func); ok {
|
||||||
|
if recv := fn.Type().(*types.Signature).Recv(); recv != nil {
|
||||||
|
_, T := ReceiverNamed(recv)
|
||||||
|
return T != nil &&
|
||||||
|
IsTypeNamed(T, pkgPath, typeName) &&
|
||||||
|
slices.Contains(names, fn.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
48
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/types.go
generated
vendored
48
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/types.go
generated
vendored
|
|
@ -2,8 +2,20 @@
|
||||||
// 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 typesinternal provides access to internal go/types APIs that are not
|
// Package typesinternal provides helpful operators for dealing with
|
||||||
// yet exported.
|
// go/types:
|
||||||
|
//
|
||||||
|
// - operators for querying typed syntax trees (e.g. [Imports], [IsFunctionNamed]);
|
||||||
|
// - functions for converting types to strings or syntax (e.g. [TypeExpr], FileQualifier]);
|
||||||
|
// - helpers for working with the [go/types] API (e.g. [NewTypesInfo]);
|
||||||
|
// - access to internal go/types APIs that are not yet
|
||||||
|
// exported (e.g. [SetUsesCgo], [ErrorCodeStartEnd], [VarKind]); and
|
||||||
|
// - common algorithms related to types (e.g. [TooNewStdSymbols]).
|
||||||
|
//
|
||||||
|
// See also:
|
||||||
|
// - [golang.org/x/tools/internal/astutil], for operations on untyped syntax;
|
||||||
|
// - [golang.org/x/tools/internal/analysisinernal], for helpers for analyzers;
|
||||||
|
// - [golang.org/x/tools/internal/refactor], for operators to compute text edits.
|
||||||
package typesinternal
|
package typesinternal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -13,6 +25,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/ast/inspector"
|
||||||
"golang.org/x/tools/internal/aliases"
|
"golang.org/x/tools/internal/aliases"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -60,6 +73,9 @@ func ErrorCodeStartEnd(err types.Error) (code ErrorCode, start, end token.Pos, o
|
||||||
// which is often excessive.)
|
// which is often excessive.)
|
||||||
//
|
//
|
||||||
// If pkg is nil, it is equivalent to [*types.Package.Name].
|
// If pkg is nil, it is equivalent to [*types.Package.Name].
|
||||||
|
//
|
||||||
|
// TODO(adonovan): all uses of this with TypeString should be
|
||||||
|
// eliminated when https://go.dev/issues/75604 is resolved.
|
||||||
func NameRelativeTo(pkg *types.Package) types.Qualifier {
|
func NameRelativeTo(pkg *types.Package) types.Qualifier {
|
||||||
return func(other *types.Package) string {
|
return func(other *types.Package) string {
|
||||||
if pkg != nil && pkg == other {
|
if pkg != nil && pkg == other {
|
||||||
|
|
@ -153,3 +169,31 @@ func NewTypesInfo() *types.Info {
|
||||||
FileVersions: map[*ast.File]string{},
|
FileVersions: map[*ast.File]string{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnclosingScope returns the innermost block logically enclosing the cursor.
|
||||||
|
func EnclosingScope(info *types.Info, cur inspector.Cursor) *types.Scope {
|
||||||
|
for cur := range cur.Enclosing() {
|
||||||
|
n := cur.Node()
|
||||||
|
// A function's Scope is associated with its FuncType.
|
||||||
|
switch f := n.(type) {
|
||||||
|
case *ast.FuncDecl:
|
||||||
|
n = f.Type
|
||||||
|
case *ast.FuncLit:
|
||||||
|
n = f.Type
|
||||||
|
}
|
||||||
|
if b := info.Scopes[n]; b != nil {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("no Scope for *ast.File")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Imports reports whether path is imported by pkg.
|
||||||
|
func Imports(pkg *types.Package, path string) bool {
|
||||||
|
for _, imp := range pkg.Imports() {
|
||||||
|
if imp.Path() == path {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
||||||
39
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/varkind.go
generated
vendored
39
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/varkind.go
generated
vendored
|
|
@ -2,39 +2,22 @@
|
||||||
// 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 typesinternal
|
//go:build go1.25
|
||||||
|
|
||||||
// TODO(adonovan): when CL 645115 lands, define the go1.25 version of
|
package typesinternal
|
||||||
// this API that actually does something.
|
|
||||||
|
|
||||||
import "go/types"
|
import "go/types"
|
||||||
|
|
||||||
type VarKind uint8
|
type VarKind = types.VarKind
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_ VarKind = iota // (not meaningful)
|
PackageVar = types.PackageVar
|
||||||
PackageVar // a package-level variable
|
LocalVar = types.LocalVar
|
||||||
LocalVar // a local variable
|
RecvVar = types.RecvVar
|
||||||
RecvVar // a method receiver variable
|
ParamVar = types.ParamVar
|
||||||
ParamVar // a function parameter variable
|
ResultVar = types.ResultVar
|
||||||
ResultVar // a function result variable
|
FieldVar = types.FieldVar
|
||||||
FieldVar // a struct field
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (kind VarKind) String() string {
|
func GetVarKind(v *types.Var) VarKind { return v.Kind() }
|
||||||
return [...]string{
|
func SetVarKind(v *types.Var, kind VarKind) { v.SetKind(kind) }
|
||||||
0: "VarKind(0)",
|
|
||||||
PackageVar: "PackageVar",
|
|
||||||
LocalVar: "LocalVar",
|
|
||||||
RecvVar: "RecvVar",
|
|
||||||
ParamVar: "ParamVar",
|
|
||||||
ResultVar: "ResultVar",
|
|
||||||
FieldVar: "FieldVar",
|
|
||||||
}[kind]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetVarKind returns an invalid VarKind.
|
|
||||||
func GetVarKind(v *types.Var) VarKind { return 0 }
|
|
||||||
|
|
||||||
// SetVarKind has no effect.
|
|
||||||
func SetVarKind(v *types.Var, kind VarKind) {}
|
|
||||||
|
|
|
||||||
39
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/varkind_go124.go
generated
vendored
Normal file
39
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/varkind_go124.go
generated
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build !go1.25
|
||||||
|
|
||||||
|
package typesinternal
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
type VarKind uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ VarKind = iota // (not meaningful)
|
||||||
|
PackageVar // a package-level variable
|
||||||
|
LocalVar // a local variable
|
||||||
|
RecvVar // a method receiver variable
|
||||||
|
ParamVar // a function parameter variable
|
||||||
|
ResultVar // a function result variable
|
||||||
|
FieldVar // a struct field
|
||||||
|
)
|
||||||
|
|
||||||
|
func (kind VarKind) String() string {
|
||||||
|
return [...]string{
|
||||||
|
0: "VarKind(0)",
|
||||||
|
PackageVar: "PackageVar",
|
||||||
|
LocalVar: "LocalVar",
|
||||||
|
RecvVar: "RecvVar",
|
||||||
|
ParamVar: "ParamVar",
|
||||||
|
ResultVar: "ResultVar",
|
||||||
|
FieldVar: "FieldVar",
|
||||||
|
}[kind]
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVarKind returns an invalid VarKind.
|
||||||
|
func GetVarKind(v *types.Var) VarKind { return 0 }
|
||||||
|
|
||||||
|
// SetVarKind has no effect.
|
||||||
|
func SetVarKind(v *types.Var, kind VarKind) {}
|
||||||
17
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go
generated
vendored
17
src/cmd/vendor/golang.org/x/tools/internal/typesinternal/zerovalue.go
generated
vendored
|
|
@ -204,23 +204,12 @@ func ZeroExpr(t types.Type, qual types.Qualifier) (_ ast.Expr, isValid bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsZeroExpr uses simple syntactic heuristics to report whether expr
|
|
||||||
// is a obvious zero value, such as 0, "", nil, or false.
|
|
||||||
// It cannot do better without type information.
|
|
||||||
func IsZeroExpr(expr ast.Expr) bool {
|
|
||||||
switch e := expr.(type) {
|
|
||||||
case *ast.BasicLit:
|
|
||||||
return e.Value == "0" || e.Value == `""`
|
|
||||||
case *ast.Ident:
|
|
||||||
return e.Name == "nil" || e.Name == "false"
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TypeExpr returns syntax for the specified type. References to named types
|
// TypeExpr returns syntax for the specified type. References to named types
|
||||||
// are qualified by an appropriate (optional) qualifier function.
|
// are qualified by an appropriate (optional) qualifier function.
|
||||||
// It may panic for types such as Tuple or Union.
|
// It may panic for types such as Tuple or Union.
|
||||||
|
//
|
||||||
|
// See also https://go.dev/issues/75604, which will provide a robust
|
||||||
|
// Type-to-valid-Go-syntax formatter.
|
||||||
func TypeExpr(t types.Type, qual types.Qualifier) ast.Expr {
|
func TypeExpr(t types.Type, qual types.Qualifier) ast.Expr {
|
||||||
switch t := t.(type) {
|
switch t := t.(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
|
|
|
||||||
13
src/cmd/vendor/modules.txt
vendored
13
src/cmd/vendor/modules.txt
vendored
|
|
@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm
|
||||||
# golang.org/x/build v0.0.0-20250806225920-b7c66c047964
|
# golang.org/x/build v0.0.0-20250806225920-b7c66c047964
|
||||||
## explicit; go 1.23.0
|
## explicit; go 1.23.0
|
||||||
golang.org/x/build/relnote
|
golang.org/x/build/relnote
|
||||||
# golang.org/x/mod v0.28.0
|
# golang.org/x/mod v0.29.0
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/mod/internal/lazyregexp
|
golang.org/x/mod/internal/lazyregexp
|
||||||
golang.org/x/mod/modfile
|
golang.org/x/mod/modfile
|
||||||
|
|
@ -43,12 +43,12 @@ golang.org/x/mod/zip
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/sync/errgroup
|
golang.org/x/sync/errgroup
|
||||||
golang.org/x/sync/semaphore
|
golang.org/x/sync/semaphore
|
||||||
# golang.org/x/sys v0.36.0
|
# golang.org/x/sys v0.37.0
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/sys/plan9
|
golang.org/x/sys/plan9
|
||||||
golang.org/x/sys/unix
|
golang.org/x/sys/unix
|
||||||
golang.org/x/sys/windows
|
golang.org/x/sys/windows
|
||||||
# golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053
|
# golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/telemetry
|
golang.org/x/telemetry
|
||||||
golang.org/x/telemetry/counter
|
golang.org/x/telemetry/counter
|
||||||
|
|
@ -63,7 +63,7 @@ golang.org/x/telemetry/internal/upload
|
||||||
# golang.org/x/term v0.34.0
|
# golang.org/x/term v0.34.0
|
||||||
## explicit; go 1.23.0
|
## explicit; go 1.23.0
|
||||||
golang.org/x/term
|
golang.org/x/term
|
||||||
# golang.org/x/text v0.29.0
|
# golang.org/x/text v0.30.0
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/text/cases
|
golang.org/x/text/cases
|
||||||
golang.org/x/text/internal
|
golang.org/x/text/internal
|
||||||
|
|
@ -73,7 +73,7 @@ golang.org/x/text/internal/tag
|
||||||
golang.org/x/text/language
|
golang.org/x/text/language
|
||||||
golang.org/x/text/transform
|
golang.org/x/text/transform
|
||||||
golang.org/x/text/unicode/norm
|
golang.org/x/text/unicode/norm
|
||||||
# golang.org/x/tools v0.37.1-0.20250924232827-4df13e317ce4
|
# golang.org/x/tools v0.38.1-0.20251015192825-7d9453ccc0f5
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/tools/cmd/bisect
|
golang.org/x/tools/cmd/bisect
|
||||||
golang.org/x/tools/cover
|
golang.org/x/tools/cover
|
||||||
|
|
@ -97,7 +97,6 @@ golang.org/x/tools/go/analysis/passes/hostport
|
||||||
golang.org/x/tools/go/analysis/passes/httpresponse
|
golang.org/x/tools/go/analysis/passes/httpresponse
|
||||||
golang.org/x/tools/go/analysis/passes/ifaceassert
|
golang.org/x/tools/go/analysis/passes/ifaceassert
|
||||||
golang.org/x/tools/go/analysis/passes/inspect
|
golang.org/x/tools/go/analysis/passes/inspect
|
||||||
golang.org/x/tools/go/analysis/passes/internal/analysisutil
|
|
||||||
golang.org/x/tools/go/analysis/passes/loopclosure
|
golang.org/x/tools/go/analysis/passes/loopclosure
|
||||||
golang.org/x/tools/go/analysis/passes/lostcancel
|
golang.org/x/tools/go/analysis/passes/lostcancel
|
||||||
golang.org/x/tools/go/analysis/passes/nilfunc
|
golang.org/x/tools/go/analysis/passes/nilfunc
|
||||||
|
|
@ -133,6 +132,8 @@ golang.org/x/tools/internal/diff/lcs
|
||||||
golang.org/x/tools/internal/facts
|
golang.org/x/tools/internal/facts
|
||||||
golang.org/x/tools/internal/fmtstr
|
golang.org/x/tools/internal/fmtstr
|
||||||
golang.org/x/tools/internal/moreiters
|
golang.org/x/tools/internal/moreiters
|
||||||
|
golang.org/x/tools/internal/packagepath
|
||||||
|
golang.org/x/tools/internal/refactor
|
||||||
golang.org/x/tools/internal/stdlib
|
golang.org/x/tools/internal/stdlib
|
||||||
golang.org/x/tools/internal/typeparams
|
golang.org/x/tools/internal/typeparams
|
||||||
golang.org/x/tools/internal/typesinternal
|
golang.org/x/tools/internal/typesinternal
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@ module std
|
||||||
go 1.26
|
go 1.26
|
||||||
|
|
||||||
require (
|
require (
|
||||||
golang.org/x/crypto v0.42.0
|
golang.org/x/crypto v0.43.0
|
||||||
golang.org/x/net v0.44.1-0.20251002015445-edb764c2296f
|
golang.org/x/net v0.46.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
golang.org/x/sys v0.36.0 // indirect
|
golang.org/x/sys v0.37.0 // indirect
|
||||||
golang.org/x/text v0.29.0 // indirect
|
golang.org/x/text v0.30.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
16
src/go.sum
16
src/go.sum
|
|
@ -1,8 +1,8 @@
|
||||||
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||||
golang.org/x/net v0.44.1-0.20251002015445-edb764c2296f h1:vNklv+oJQSYNGsWXHoCPi2MHMcpj9/Q7aBhvvfnJvGg=
|
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||||
golang.org/x/net v0.44.1-0.20251002015445-edb764c2296f/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||||
|
|
|
||||||
|
|
@ -11695,6 +11695,12 @@ func (ws *http2priorityWriteSchedulerRFC9218) AdjustStream(streamID uint32, prio
|
||||||
q.prev.next = q
|
q.prev.next = q
|
||||||
q.next.prev = q
|
q.next.prev = q
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the metadata.
|
||||||
|
ws.streams[streamID] = http2streamMetadata{
|
||||||
|
location: q,
|
||||||
|
priority: priority,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *http2priorityWriteSchedulerRFC9218) Push(wr http2FrameWriteRequest) {
|
func (ws *http2priorityWriteSchedulerRFC9218) Push(wr http2FrameWriteRequest) {
|
||||||
|
|
|
||||||
11
src/vendor/golang.org/x/text/unicode/bidi/core.go
generated
vendored
11
src/vendor/golang.org/x/text/unicode/bidi/core.go
generated
vendored
|
|
@ -427,13 +427,6 @@ type isolatingRunSequence struct {
|
||||||
|
|
||||||
func (i *isolatingRunSequence) Len() int { return len(i.indexes) }
|
func (i *isolatingRunSequence) Len() int { return len(i.indexes) }
|
||||||
|
|
||||||
func maxLevel(a, b level) level {
|
|
||||||
if a > b {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rule X10, second bullet: Determine the start-of-sequence (sos) and end-of-sequence (eos) types,
|
// Rule X10, second bullet: Determine the start-of-sequence (sos) and end-of-sequence (eos) types,
|
||||||
// either L or R, for each isolating run sequence.
|
// either L or R, for each isolating run sequence.
|
||||||
func (p *paragraph) isolatingRunSequence(indexes []int) *isolatingRunSequence {
|
func (p *paragraph) isolatingRunSequence(indexes []int) *isolatingRunSequence {
|
||||||
|
|
@ -474,8 +467,8 @@ func (p *paragraph) isolatingRunSequence(indexes []int) *isolatingRunSequence {
|
||||||
indexes: indexes,
|
indexes: indexes,
|
||||||
types: types,
|
types: types,
|
||||||
level: level,
|
level: level,
|
||||||
sos: typeForLevel(maxLevel(prevLevel, level)),
|
sos: typeForLevel(max(prevLevel, level)),
|
||||||
eos: typeForLevel(maxLevel(succLevel, level)),
|
eos: typeForLevel(max(succLevel, level)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
8
src/vendor/modules.txt
vendored
8
src/vendor/modules.txt
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
# golang.org/x/crypto v0.42.0
|
# golang.org/x/crypto v0.43.0
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/crypto/chacha20
|
golang.org/x/crypto/chacha20
|
||||||
golang.org/x/crypto/chacha20poly1305
|
golang.org/x/crypto/chacha20poly1305
|
||||||
|
|
@ -6,7 +6,7 @@ golang.org/x/crypto/cryptobyte
|
||||||
golang.org/x/crypto/cryptobyte/asn1
|
golang.org/x/crypto/cryptobyte/asn1
|
||||||
golang.org/x/crypto/internal/alias
|
golang.org/x/crypto/internal/alias
|
||||||
golang.org/x/crypto/internal/poly1305
|
golang.org/x/crypto/internal/poly1305
|
||||||
# golang.org/x/net v0.44.1-0.20251002015445-edb764c2296f
|
# golang.org/x/net v0.46.0
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/net/dns/dnsmessage
|
golang.org/x/net/dns/dnsmessage
|
||||||
golang.org/x/net/http/httpguts
|
golang.org/x/net/http/httpguts
|
||||||
|
|
@ -15,10 +15,10 @@ golang.org/x/net/http2/hpack
|
||||||
golang.org/x/net/idna
|
golang.org/x/net/idna
|
||||||
golang.org/x/net/lif
|
golang.org/x/net/lif
|
||||||
golang.org/x/net/nettest
|
golang.org/x/net/nettest
|
||||||
# golang.org/x/sys v0.36.0
|
# golang.org/x/sys v0.37.0
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/sys/cpu
|
golang.org/x/sys/cpu
|
||||||
# golang.org/x/text v0.29.0
|
# golang.org/x/text v0.30.0
|
||||||
## explicit; go 1.24.0
|
## explicit; go 1.24.0
|
||||||
golang.org/x/text/secure/bidirule
|
golang.org/x/text/secure/bidirule
|
||||||
golang.org/x/text/transform
|
golang.org/x/text/transform
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue