mirror of
https://github.com/go-delve/delve.git
synced 2025-08-05 21:16:59 +02:00
*: update golang.org/x/tools
This fixes the following error when running `make test`: ``` # golang.org/x/tools/internal/tokeninternal vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go:78:9: invalid array length -delta * delta (constant -256 of type int64) ``` This is the minimum version update which fixes the problem. It bumps our go.mod up to 1.22, but since we also bumped our max supported version I think this is ok.
This commit is contained in:
parent
1753a054ac
commit
e30598333a
0
_fixtures/buildtest/__debug_bin2807893743
Normal file
0
_fixtures/buildtest/__debug_bin2807893743
Normal file
6
go.mod
6
go.mod
@ -1,6 +1,6 @@
|
|||||||
module github.com/go-delve/delve
|
module github.com/go-delve/delve
|
||||||
|
|
||||||
go 1.21
|
go 1.22.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cilium/ebpf v0.11.0
|
github.com/cilium/ebpf v0.11.0
|
||||||
@ -18,7 +18,7 @@ require (
|
|||||||
golang.org/x/arch v0.11.0
|
golang.org/x/arch v0.11.0
|
||||||
golang.org/x/sys v0.26.0
|
golang.org/x/sys v0.26.0
|
||||||
golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5
|
golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5
|
||||||
golang.org/x/tools v0.14.0
|
golang.org/x/tools v0.26.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -29,6 +29,6 @@ require (
|
|||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
|
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
|
||||||
golang.org/x/mod v0.20.0 // indirect
|
golang.org/x/mod v0.21.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
)
|
)
|
||||||
|
12
go.sum
12
go.sum
@ -12,8 +12,8 @@ github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx
|
|||||||
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62 h1:IGtvsNyIuRjl04XAOFGACozgUD7A82UffYxZt4DWbvA=
|
github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62 h1:IGtvsNyIuRjl04XAOFGACozgUD7A82UffYxZt4DWbvA=
|
||||||
github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62/go.mod h1:biJCRbqp51wS+I92HMqn5H8/A0PAhxn2vyOT+JqhiGI=
|
github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62/go.mod h1:biJCRbqp51wS+I92HMqn5H8/A0PAhxn2vyOT+JqhiGI=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-dap v0.12.0 h1:rVcjv3SyMIrpaOoTAdFDyHs99CwVOItIJGKLQFQhNeM=
|
github.com/google/go-dap v0.12.0 h1:rVcjv3SyMIrpaOoTAdFDyHs99CwVOItIJGKLQFQhNeM=
|
||||||
github.com/google/go-dap v0.12.0/go.mod h1:tNjCASCm5cqePi/RVXXWEVqtnNLV1KTWtYOqu6rZNzc=
|
github.com/google/go-dap v0.12.0/go.mod h1:tNjCASCm5cqePi/RVXXWEVqtnNLV1KTWtYOqu6rZNzc=
|
||||||
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||||
@ -48,8 +48,8 @@ golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4=
|
|||||||
golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI=
|
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI=
|
||||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@ -59,8 +59,8 @@ golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
|||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5 h1:TCDqnvbBsFapViksHcHySl/sW4+rTGNIAoJJesHRuMM=
|
golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5 h1:TCDqnvbBsFapViksHcHySl/sW4+rTGNIAoJJesHRuMM=
|
||||||
golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5/go.mod h1:8nZWdGp9pq73ZI//QJyckMQab3yq7hoWi7SI0UIusVI=
|
golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5/go.mod h1:8nZWdGp9pq73ZI//QJyckMQab3yq7hoWi7SI0UIusVI=
|
||||||
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
|
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||||
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
|
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
102
vendor/golang.org/x/sys/execabs/execabs.go
generated
vendored
102
vendor/golang.org/x/sys/execabs/execabs.go
generated
vendored
@ -1,102 +0,0 @@
|
|||||||
// Copyright 2020 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package execabs is a drop-in replacement for os/exec
|
|
||||||
// that requires PATH lookups to find absolute paths.
|
|
||||||
// That is, execabs.Command("cmd") runs the same PATH lookup
|
|
||||||
// as exec.Command("cmd"), but if the result is a path
|
|
||||||
// which is relative, the Run and Start methods will report
|
|
||||||
// an error instead of running the executable.
|
|
||||||
//
|
|
||||||
// See https://blog.golang.org/path-security for more information
|
|
||||||
// about when it may be necessary or appropriate to use this package.
|
|
||||||
package execabs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrNotFound is the error resulting if a path search failed to find an executable file.
|
|
||||||
// It is an alias for exec.ErrNotFound.
|
|
||||||
var ErrNotFound = exec.ErrNotFound
|
|
||||||
|
|
||||||
// Cmd represents an external command being prepared or run.
|
|
||||||
// It is an alias for exec.Cmd.
|
|
||||||
type Cmd = exec.Cmd
|
|
||||||
|
|
||||||
// Error is returned by LookPath when it fails to classify a file as an executable.
|
|
||||||
// It is an alias for exec.Error.
|
|
||||||
type Error = exec.Error
|
|
||||||
|
|
||||||
// An ExitError reports an unsuccessful exit by a command.
|
|
||||||
// It is an alias for exec.ExitError.
|
|
||||||
type ExitError = exec.ExitError
|
|
||||||
|
|
||||||
func relError(file, path string) error {
|
|
||||||
return fmt.Errorf("%s resolves to executable in current directory (.%c%s)", file, filepath.Separator, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LookPath searches for an executable named file in the directories
|
|
||||||
// named by the PATH environment variable. If file contains a slash,
|
|
||||||
// it is tried directly and the PATH is not consulted. The result will be
|
|
||||||
// an absolute path.
|
|
||||||
//
|
|
||||||
// LookPath differs from exec.LookPath in its handling of PATH lookups,
|
|
||||||
// which are used for file names without slashes. If exec.LookPath's
|
|
||||||
// PATH lookup would have returned an executable from the current directory,
|
|
||||||
// LookPath instead returns an error.
|
|
||||||
func LookPath(file string) (string, error) {
|
|
||||||
path, err := exec.LookPath(file)
|
|
||||||
if err != nil && !isGo119ErrDot(err) {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if filepath.Base(file) == file && !filepath.IsAbs(path) {
|
|
||||||
return "", relError(file, path)
|
|
||||||
}
|
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func fixCmd(name string, cmd *exec.Cmd) {
|
|
||||||
if filepath.Base(name) == name && !filepath.IsAbs(cmd.Path) && !isGo119ErrFieldSet(cmd) {
|
|
||||||
// exec.Command was called with a bare binary name and
|
|
||||||
// exec.LookPath returned a path which is not absolute.
|
|
||||||
// Set cmd.lookPathErr and clear cmd.Path so that it
|
|
||||||
// cannot be run.
|
|
||||||
lookPathErr := (*error)(unsafe.Pointer(reflect.ValueOf(cmd).Elem().FieldByName("lookPathErr").Addr().Pointer()))
|
|
||||||
if *lookPathErr == nil {
|
|
||||||
*lookPathErr = relError(name, cmd.Path)
|
|
||||||
}
|
|
||||||
cmd.Path = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CommandContext is like Command but includes a context.
|
|
||||||
//
|
|
||||||
// The provided context is used to kill the process (by calling os.Process.Kill)
|
|
||||||
// if the context becomes done before the command completes on its own.
|
|
||||||
func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd {
|
|
||||||
cmd := exec.CommandContext(ctx, name, arg...)
|
|
||||||
fixCmd(name, cmd)
|
|
||||||
return cmd
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the Cmd struct to execute the named program with the given arguments.
|
|
||||||
// See exec.Command for most details.
|
|
||||||
//
|
|
||||||
// Command differs from exec.Command in its handling of PATH lookups,
|
|
||||||
// which are used when the program name contains no slashes.
|
|
||||||
// If exec.Command would have returned an exec.Cmd configured to run an
|
|
||||||
// executable from the current directory, Command instead
|
|
||||||
// returns an exec.Cmd that will return an error from Start or Run.
|
|
||||||
func Command(name string, arg ...string) *exec.Cmd {
|
|
||||||
cmd := exec.Command(name, arg...)
|
|
||||||
fixCmd(name, cmd)
|
|
||||||
return cmd
|
|
||||||
}
|
|
17
vendor/golang.org/x/sys/execabs/execabs_go118.go
generated
vendored
17
vendor/golang.org/x/sys/execabs/execabs_go118.go
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
// Copyright 2022 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.19
|
|
||||||
|
|
||||||
package execabs
|
|
||||||
|
|
||||||
import "os/exec"
|
|
||||||
|
|
||||||
func isGo119ErrDot(err error) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isGo119ErrFieldSet(cmd *exec.Cmd) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
20
vendor/golang.org/x/sys/execabs/execabs_go119.go
generated
vendored
20
vendor/golang.org/x/sys/execabs/execabs_go119.go
generated
vendored
@ -1,20 +0,0 @@
|
|||||||
// Copyright 2022 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.19
|
|
||||||
|
|
||||||
package execabs
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"os/exec"
|
|
||||||
)
|
|
||||||
|
|
||||||
func isGo119ErrDot(err error) bool {
|
|
||||||
return errors.Is(err, exec.ErrDot)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isGo119ErrFieldSet(cmd *exec.Cmd) bool {
|
|
||||||
return cmd.Err != nil
|
|
||||||
}
|
|
4
vendor/golang.org/x/tools/LICENSE
generated
vendored
4
vendor/golang.org/x/tools/LICENSE
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
Copyright 2009 The Go Authors.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are
|
modification, are permitted provided that the following conditions are
|
||||||
@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
|
|||||||
copyright notice, this list of conditions and the following disclaimer
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
in the documentation and/or other materials provided with the
|
in the documentation and/or other materials provided with the
|
||||||
distribution.
|
distribution.
|
||||||
* Neither the name of Google Inc. nor the names of its
|
* Neither the name of Google LLC nor the names of its
|
||||||
contributors may be used to endorse or promote products derived from
|
contributors may be used to endorse or promote products derived from
|
||||||
this software without specific prior written permission.
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go
generated
vendored
2
vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go
generated
vendored
@ -47,7 +47,7 @@ import (
|
|||||||
func Find(importPath, srcDir string) (filename, path string) {
|
func Find(importPath, srcDir string) (filename, path string) {
|
||||||
cmd := exec.Command("go", "list", "-json", "-export", "--", importPath)
|
cmd := exec.Command("go", "list", "-json", "-export", "--", importPath)
|
||||||
cmd.Dir = srcDir
|
cmd.Dir = srcDir
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
48
vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
generated
vendored
48
vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
generated
vendored
@ -1,48 +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 packagesdriver fetches type sizes for go/packages and go/analysis.
|
|
||||||
package packagesdriver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/tools/internal/gocommand"
|
|
||||||
)
|
|
||||||
|
|
||||||
var debug = false
|
|
||||||
|
|
||||||
func GetSizesForArgsGolist(ctx context.Context, inv gocommand.Invocation, gocmdRunner *gocommand.Runner) (string, string, error) {
|
|
||||||
inv.Verb = "list"
|
|
||||||
inv.Args = []string{"-f", "{{context.GOARCH}} {{context.Compiler}}", "--", "unsafe"}
|
|
||||||
stdout, stderr, friendlyErr, rawErr := gocmdRunner.RunRaw(ctx, inv)
|
|
||||||
var goarch, compiler string
|
|
||||||
if rawErr != nil {
|
|
||||||
if rawErrMsg := rawErr.Error(); strings.Contains(rawErrMsg, "cannot find main module") || strings.Contains(rawErrMsg, "go.mod file not found") {
|
|
||||||
// User's running outside of a module. All bets are off. Get GOARCH and guess compiler is gc.
|
|
||||||
// TODO(matloob): Is this a problem in practice?
|
|
||||||
inv.Verb = "env"
|
|
||||||
inv.Args = []string{"GOARCH"}
|
|
||||||
envout, enverr := gocmdRunner.Run(ctx, inv)
|
|
||||||
if enverr != nil {
|
|
||||||
return "", "", enverr
|
|
||||||
}
|
|
||||||
goarch = strings.TrimSpace(envout.String())
|
|
||||||
compiler = "gc"
|
|
||||||
} else {
|
|
||||||
return "", "", friendlyErr
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fields := strings.Fields(stdout.String())
|
|
||||||
if len(fields) < 2 {
|
|
||||||
return "", "", fmt.Errorf("could not parse GOARCH and Go compiler in format \"<GOARCH> <compiler>\":\nstdout: <<%s>>\nstderr: <<%s>>",
|
|
||||||
stdout.String(), stderr.String())
|
|
||||||
}
|
|
||||||
goarch = fields[0]
|
|
||||||
compiler = fields[1]
|
|
||||||
}
|
|
||||||
return compiler, goarch, nil
|
|
||||||
}
|
|
61
vendor/golang.org/x/tools/go/packages/doc.go
generated
vendored
61
vendor/golang.org/x/tools/go/packages/doc.go
generated
vendored
@ -5,12 +5,20 @@
|
|||||||
/*
|
/*
|
||||||
Package packages loads Go packages for inspection and analysis.
|
Package packages loads Go packages for inspection and analysis.
|
||||||
|
|
||||||
The Load function takes as input a list of patterns and return a list of Package
|
The [Load] function takes as input a list of patterns and returns a
|
||||||
structs describing individual packages matched by those patterns.
|
list of [Package] values describing individual packages matched by those
|
||||||
The LoadMode controls the amount of detail in the loaded packages.
|
patterns.
|
||||||
|
A [Config] specifies configuration options, the most important of which is
|
||||||
|
the [LoadMode], which controls the amount of detail in the loaded packages.
|
||||||
|
|
||||||
Load passes most patterns directly to the underlying build tool,
|
Load passes most patterns directly to the underlying build tool.
|
||||||
but all patterns with the prefix "query=", where query is a
|
The default build tool is the go command.
|
||||||
|
Its supported patterns are described at
|
||||||
|
https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns.
|
||||||
|
Other build systems may be supported by providing a "driver";
|
||||||
|
see [The driver protocol].
|
||||||
|
|
||||||
|
All patterns with the prefix "query=", where query is a
|
||||||
non-empty string of letters from [a-z], are reserved and may be
|
non-empty string of letters from [a-z], are reserved and may be
|
||||||
interpreted as query operators.
|
interpreted as query operators.
|
||||||
|
|
||||||
@ -56,7 +64,7 @@ graph using the Imports fields.
|
|||||||
|
|
||||||
The Load function can be configured by passing a pointer to a Config as
|
The Load function can be configured by passing a pointer to a Config as
|
||||||
the first argument. A nil Config is equivalent to the zero Config, which
|
the first argument. A nil Config is equivalent to the zero Config, which
|
||||||
causes Load to run in LoadFiles mode, collecting minimal information.
|
causes Load to run in [LoadFiles] mode, collecting minimal information.
|
||||||
See the documentation for type Config for details.
|
See the documentation for type Config for details.
|
||||||
|
|
||||||
As noted earlier, the Config.Mode controls the amount of detail
|
As noted earlier, the Config.Mode controls the amount of detail
|
||||||
@ -64,9 +72,40 @@ reported about the loaded packages. See the documentation for type LoadMode
|
|||||||
for details.
|
for details.
|
||||||
|
|
||||||
Most tools should pass their command-line arguments (after any flags)
|
Most tools should pass their command-line arguments (after any flags)
|
||||||
uninterpreted to the loader, so that the loader can interpret them
|
uninterpreted to Load, so that it can interpret them
|
||||||
according to the conventions of the underlying build system.
|
according to the conventions of the underlying build system.
|
||||||
|
|
||||||
See the Example function for typical usage.
|
See the Example function for typical usage.
|
||||||
|
|
||||||
|
# The driver protocol
|
||||||
|
|
||||||
|
Load may be used to load Go packages even in Go projects that use
|
||||||
|
alternative build systems, by installing an appropriate "driver"
|
||||||
|
program for the build system and specifying its location in the
|
||||||
|
GOPACKAGESDRIVER environment variable.
|
||||||
|
For example,
|
||||||
|
https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration
|
||||||
|
explains how to use the driver for Bazel.
|
||||||
|
|
||||||
|
The driver program is responsible for interpreting patterns in its
|
||||||
|
preferred notation and reporting information about the packages that
|
||||||
|
those patterns identify. Drivers must also support the special "file="
|
||||||
|
and "pattern=" patterns described above.
|
||||||
|
|
||||||
|
The patterns are provided as positional command-line arguments. A
|
||||||
|
JSON-encoded [DriverRequest] message providing additional information
|
||||||
|
is written to the driver's standard input. The driver must write a
|
||||||
|
JSON-encoded [DriverResponse] message to its standard output. (This
|
||||||
|
message differs from the JSON schema produced by 'go list'.)
|
||||||
|
|
||||||
|
The value of the PWD environment variable seen by the driver process
|
||||||
|
is the preferred name of its working directory. (The working directory
|
||||||
|
may have other aliases due to symbolic links; see the comment on the
|
||||||
|
Dir field of [exec.Cmd] for related information.)
|
||||||
|
When the driver process emits in its response the name of a file
|
||||||
|
that is a descendant of this directory, it must use an absolute path
|
||||||
|
that has the value of PWD as a prefix, to ensure that the returned
|
||||||
|
filenames satisfy the original query.
|
||||||
*/
|
*/
|
||||||
package packages // import "golang.org/x/tools/go/packages"
|
package packages // import "golang.org/x/tools/go/packages"
|
||||||
|
|
||||||
@ -168,14 +207,6 @@ Instead, ssadump no longer requests the runtime package,
|
|||||||
but seeks it among the dependencies of the user-specified packages,
|
but seeks it among the dependencies of the user-specified packages,
|
||||||
and emits an error if it is not found.
|
and emits an error if it is not found.
|
||||||
|
|
||||||
Overlays: The Overlay field in the Config allows providing alternate contents
|
|
||||||
for Go source files, by providing a mapping from file path to contents.
|
|
||||||
go/packages will pull in new imports added in overlay files when go/packages
|
|
||||||
is run in LoadImports mode or greater.
|
|
||||||
Overlay support for the go list driver isn't complete yet: if the file doesn't
|
|
||||||
exist on disk, it will only be recognized in an overlay if it is a non-test file
|
|
||||||
and the package would be reported even without the overlay.
|
|
||||||
|
|
||||||
Questions & Tasks
|
Questions & Tasks
|
||||||
|
|
||||||
- Add GOARCH/GOOS?
|
- Add GOARCH/GOOS?
|
||||||
|
103
vendor/golang.org/x/tools/go/packages/external.go
generated
vendored
103
vendor/golang.org/x/tools/go/packages/external.go
generated
vendored
@ -2,48 +2,87 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
// This file enables an external tool to intercept package requests.
|
|
||||||
// If the tool is present then its results are used in preference to
|
|
||||||
// the go list command.
|
|
||||||
|
|
||||||
package packages
|
package packages
|
||||||
|
|
||||||
|
// This file defines the protocol that enables an external "driver"
|
||||||
|
// tool to supply package metadata in place of 'go list'.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
exec "golang.org/x/sys/execabs"
|
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The Driver Protocol
|
// DriverRequest defines the schema of a request for package metadata
|
||||||
|
// from an external driver program. The JSON-encoded DriverRequest
|
||||||
|
// message is provided to the driver program's standard input. The
|
||||||
|
// query patterns are provided as command-line arguments.
|
||||||
//
|
//
|
||||||
// The driver, given the inputs to a call to Load, returns metadata about the packages specified.
|
// See the package documentation for an overview.
|
||||||
// This allows for different build systems to support go/packages by telling go/packages how the
|
type DriverRequest struct {
|
||||||
// packages' source is organized.
|
|
||||||
// The driver is a binary, either specified by the GOPACKAGESDRIVER environment variable or in
|
|
||||||
// the path as gopackagesdriver. It's given the inputs to load in its argv. See the package
|
|
||||||
// documentation in doc.go for the full description of the patterns that need to be supported.
|
|
||||||
// A driver receives as a JSON-serialized driverRequest struct in standard input and will
|
|
||||||
// produce a JSON-serialized driverResponse (see definition in packages.go) in its standard output.
|
|
||||||
|
|
||||||
// driverRequest is used to provide the portion of Load's Config that is needed by a driver.
|
|
||||||
type driverRequest struct {
|
|
||||||
Mode LoadMode `json:"mode"`
|
Mode LoadMode `json:"mode"`
|
||||||
|
|
||||||
// Env specifies the environment the underlying build system should be run in.
|
// Env specifies the environment the underlying build system should be run in.
|
||||||
Env []string `json:"env"`
|
Env []string `json:"env"`
|
||||||
|
|
||||||
// BuildFlags are flags that should be passed to the underlying build system.
|
// BuildFlags are flags that should be passed to the underlying build system.
|
||||||
BuildFlags []string `json:"build_flags"`
|
BuildFlags []string `json:"build_flags"`
|
||||||
|
|
||||||
// Tests specifies whether the patterns should also return test packages.
|
// Tests specifies whether the patterns should also return test packages.
|
||||||
Tests bool `json:"tests"`
|
Tests bool `json:"tests"`
|
||||||
// Overlay maps file paths (relative to the driver's working directory) to the byte contents
|
|
||||||
// of overlay files.
|
// Overlay maps file paths (relative to the driver's working directory)
|
||||||
|
// to the contents of overlay files (see Config.Overlay).
|
||||||
Overlay map[string][]byte `json:"overlay"`
|
Overlay map[string][]byte `json:"overlay"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DriverResponse defines the schema of a response from an external
|
||||||
|
// driver program, providing the results of a query for package
|
||||||
|
// metadata. The driver program must write a JSON-encoded
|
||||||
|
// DriverResponse message to its standard output.
|
||||||
|
//
|
||||||
|
// See the package documentation for an overview.
|
||||||
|
type DriverResponse struct {
|
||||||
|
// NotHandled is returned if the request can't be handled by the current
|
||||||
|
// driver. If an external driver returns a response with NotHandled, the
|
||||||
|
// rest of the DriverResponse is ignored, and go/packages will fallback
|
||||||
|
// to the next driver. If go/packages is extended in the future to support
|
||||||
|
// lists of multiple drivers, go/packages will fall back to the next driver.
|
||||||
|
NotHandled bool
|
||||||
|
|
||||||
|
// Compiler and Arch are the arguments pass of types.SizesFor
|
||||||
|
// to get a types.Sizes to use when type checking.
|
||||||
|
Compiler string
|
||||||
|
Arch string
|
||||||
|
|
||||||
|
// Roots is the set of package IDs that make up the root packages.
|
||||||
|
// We have to encode this separately because when we encode a single package
|
||||||
|
// we cannot know if it is one of the roots as that requires knowledge of the
|
||||||
|
// graph it is part of.
|
||||||
|
Roots []string `json:",omitempty"`
|
||||||
|
|
||||||
|
// Packages is the full set of packages in the graph.
|
||||||
|
// The packages are not connected into a graph.
|
||||||
|
// The Imports if populated will be stubs that only have their ID set.
|
||||||
|
// Imports will be connected and then type and syntax information added in a
|
||||||
|
// later pass (see refine).
|
||||||
|
Packages []*Package
|
||||||
|
|
||||||
|
// GoVersion is the minor version number used by the driver
|
||||||
|
// (e.g. the go command on the PATH) when selecting .go files.
|
||||||
|
// Zero means unknown.
|
||||||
|
GoVersion int
|
||||||
|
}
|
||||||
|
|
||||||
|
// driver is the type for functions that query the build system for the
|
||||||
|
// packages named by the patterns.
|
||||||
|
type driver func(cfg *Config, patterns ...string) (*DriverResponse, error)
|
||||||
|
|
||||||
// findExternalDriver returns the file path of a tool that supplies
|
// findExternalDriver returns the file path of a tool that supplies
|
||||||
// the build system package structure, or "" if not found."
|
// the build system package structure, or "" if not found.
|
||||||
// If GOPACKAGESDRIVER is set in the environment findExternalTool returns its
|
// If GOPACKAGESDRIVER is set in the environment findExternalTool returns its
|
||||||
// value, otherwise it searches for a binary named gopackagesdriver on the PATH.
|
// value, otherwise it searches for a binary named gopackagesdriver on the PATH.
|
||||||
func findExternalDriver(cfg *Config) driver {
|
func findExternalDriver(cfg *Config) driver {
|
||||||
@ -64,8 +103,8 @@ func findExternalDriver(cfg *Config) driver {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return func(cfg *Config, words ...string) (*driverResponse, error) {
|
return func(cfg *Config, words ...string) (*DriverResponse, error) {
|
||||||
req, err := json.Marshal(driverRequest{
|
req, err := json.Marshal(DriverRequest{
|
||||||
Mode: cfg.Mode,
|
Mode: cfg.Mode,
|
||||||
Env: cfg.Env,
|
Env: cfg.Env,
|
||||||
BuildFlags: cfg.BuildFlags,
|
BuildFlags: cfg.BuildFlags,
|
||||||
@ -80,7 +119,19 @@ func findExternalDriver(cfg *Config) driver {
|
|||||||
stderr := new(bytes.Buffer)
|
stderr := new(bytes.Buffer)
|
||||||
cmd := exec.CommandContext(cfg.Context, tool, words...)
|
cmd := exec.CommandContext(cfg.Context, tool, words...)
|
||||||
cmd.Dir = cfg.Dir
|
cmd.Dir = cfg.Dir
|
||||||
cmd.Env = cfg.Env
|
// The cwd gets resolved to the real path. On Darwin, where
|
||||||
|
// /tmp is a symlink, this breaks anything that expects the
|
||||||
|
// working directory to keep the original path, including the
|
||||||
|
// go command when dealing with modules.
|
||||||
|
//
|
||||||
|
// os.Getwd stdlib has a special feature where if the
|
||||||
|
// cwd and the PWD are the same node then it trusts
|
||||||
|
// the PWD, so by setting it in the env for the child
|
||||||
|
// process we fix up all the paths returned by the go
|
||||||
|
// command.
|
||||||
|
//
|
||||||
|
// (See similar trick in Invocation.run in ../../internal/gocommand/invoke.go)
|
||||||
|
cmd.Env = append(slicesClip(cfg.Env), "PWD="+cfg.Dir)
|
||||||
cmd.Stdin = bytes.NewReader(req)
|
cmd.Stdin = bytes.NewReader(req)
|
||||||
cmd.Stdout = buf
|
cmd.Stdout = buf
|
||||||
cmd.Stderr = stderr
|
cmd.Stderr = stderr
|
||||||
@ -92,10 +143,14 @@ func findExternalDriver(cfg *Config) driver {
|
|||||||
fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr)
|
fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr)
|
||||||
}
|
}
|
||||||
|
|
||||||
var response driverResponse
|
var response DriverResponse
|
||||||
if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
|
if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &response, nil
|
return &response, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// slicesClip removes unused capacity from the slice, returning s[:len(s):len(s)].
|
||||||
|
// TODO(adonovan): use go1.21 slices.Clip.
|
||||||
|
func slicesClip[S ~[]E, E any](s S) S { return s[:len(s):len(s)] }
|
||||||
|
237
vendor/golang.org/x/tools/go/packages/golist.go
generated
vendored
237
vendor/golang.org/x/tools/go/packages/golist.go
generated
vendored
@ -11,6 +11,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -20,8 +21,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
exec "golang.org/x/sys/execabs"
|
|
||||||
"golang.org/x/tools/go/internal/packagesdriver"
|
|
||||||
"golang.org/x/tools/internal/gocommand"
|
"golang.org/x/tools/internal/gocommand"
|
||||||
"golang.org/x/tools/internal/packagesinternal"
|
"golang.org/x/tools/internal/packagesinternal"
|
||||||
)
|
)
|
||||||
@ -35,23 +34,23 @@ type goTooOldError struct {
|
|||||||
error
|
error
|
||||||
}
|
}
|
||||||
|
|
||||||
// responseDeduper wraps a driverResponse, deduplicating its contents.
|
// responseDeduper wraps a DriverResponse, deduplicating its contents.
|
||||||
type responseDeduper struct {
|
type responseDeduper struct {
|
||||||
seenRoots map[string]bool
|
seenRoots map[string]bool
|
||||||
seenPackages map[string]*Package
|
seenPackages map[string]*Package
|
||||||
dr *driverResponse
|
dr *DriverResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDeduper() *responseDeduper {
|
func newDeduper() *responseDeduper {
|
||||||
return &responseDeduper{
|
return &responseDeduper{
|
||||||
dr: &driverResponse{},
|
dr: &DriverResponse{},
|
||||||
seenRoots: map[string]bool{},
|
seenRoots: map[string]bool{},
|
||||||
seenPackages: map[string]*Package{},
|
seenPackages: map[string]*Package{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// addAll fills in r with a driverResponse.
|
// addAll fills in r with a DriverResponse.
|
||||||
func (r *responseDeduper) addAll(dr *driverResponse) {
|
func (r *responseDeduper) addAll(dr *DriverResponse) {
|
||||||
for _, pkg := range dr.Packages {
|
for _, pkg := range dr.Packages {
|
||||||
r.addPackage(pkg)
|
r.addPackage(pkg)
|
||||||
}
|
}
|
||||||
@ -128,7 +127,7 @@ func (state *golistState) mustGetEnv() map[string]string {
|
|||||||
// goListDriver uses the go list command to interpret the patterns and produce
|
// goListDriver uses the go list command to interpret the patterns and produce
|
||||||
// the build system package structure.
|
// the build system package structure.
|
||||||
// See driver for more details.
|
// See driver for more details.
|
||||||
func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
|
func goListDriver(cfg *Config, patterns ...string) (_ *DriverResponse, err error) {
|
||||||
// Make sure that any asynchronous go commands are killed when we return.
|
// Make sure that any asynchronous go commands are killed when we return.
|
||||||
parentCtx := cfg.Context
|
parentCtx := cfg.Context
|
||||||
if parentCtx == nil {
|
if parentCtx == nil {
|
||||||
@ -146,16 +145,18 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fill in response.Sizes asynchronously if necessary.
|
// Fill in response.Sizes asynchronously if necessary.
|
||||||
var sizeserr error
|
|
||||||
var sizeswg sync.WaitGroup
|
|
||||||
if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 {
|
if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 {
|
||||||
sizeswg.Add(1)
|
errCh := make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
compiler, arch, err := packagesdriver.GetSizesForArgsGolist(ctx, state.cfgInvocation(), cfg.gocmdRunner)
|
compiler, arch, err := getSizesForArgs(ctx, state.cfgInvocation(), cfg.gocmdRunner)
|
||||||
sizeserr = err
|
|
||||||
response.dr.Compiler = compiler
|
response.dr.Compiler = compiler
|
||||||
response.dr.Arch = arch
|
response.dr.Arch = arch
|
||||||
sizeswg.Done()
|
errCh <- err
|
||||||
|
}()
|
||||||
|
defer func() {
|
||||||
|
if sizesErr := <-errCh; sizesErr != nil {
|
||||||
|
err = sizesErr
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,87 +209,10 @@ extractQueries:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only use go/packages' overlay processing if we're using a Go version
|
// (We may yet return an error due to defer.)
|
||||||
// below 1.16. Otherwise, go list handles it.
|
|
||||||
if goVersion, err := state.getGoVersion(); err == nil && goVersion < 16 {
|
|
||||||
modifiedPkgs, needPkgs, err := state.processGolistOverlay(response)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var containsCandidates []string
|
|
||||||
if len(containFiles) > 0 {
|
|
||||||
containsCandidates = append(containsCandidates, modifiedPkgs...)
|
|
||||||
containsCandidates = append(containsCandidates, needPkgs...)
|
|
||||||
}
|
|
||||||
if err := state.addNeededOverlayPackages(response, needPkgs); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Check candidate packages for containFiles.
|
|
||||||
if len(containFiles) > 0 {
|
|
||||||
for _, id := range containsCandidates {
|
|
||||||
pkg, ok := response.seenPackages[id]
|
|
||||||
if !ok {
|
|
||||||
response.addPackage(&Package{
|
|
||||||
ID: id,
|
|
||||||
Errors: []Error{{
|
|
||||||
Kind: ListError,
|
|
||||||
Msg: fmt.Sprintf("package %s expected but not seen", id),
|
|
||||||
}},
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, f := range containFiles {
|
|
||||||
for _, g := range pkg.GoFiles {
|
|
||||||
if sameFile(f, g) {
|
|
||||||
response.addRoot(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Add root for any package that matches a pattern. This applies only to
|
|
||||||
// packages that are modified by overlays, since they are not added as
|
|
||||||
// roots automatically.
|
|
||||||
for _, pattern := range restPatterns {
|
|
||||||
match := matchPattern(pattern)
|
|
||||||
for _, pkgID := range modifiedPkgs {
|
|
||||||
pkg, ok := response.seenPackages[pkgID]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if match(pkg.PkgPath) {
|
|
||||||
response.addRoot(pkg.ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sizeswg.Wait()
|
|
||||||
if sizeserr != nil {
|
|
||||||
return nil, sizeserr
|
|
||||||
}
|
|
||||||
return response.dr, nil
|
return response.dr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *golistState) addNeededOverlayPackages(response *responseDeduper, pkgs []string) error {
|
|
||||||
if len(pkgs) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
dr, err := state.createDriverResponse(pkgs...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, pkg := range dr.Packages {
|
|
||||||
response.addPackage(pkg)
|
|
||||||
}
|
|
||||||
_, needPkgs, err := state.processGolistOverlay(response)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return state.addNeededOverlayPackages(response, needPkgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (state *golistState) runContainsQueries(response *responseDeduper, queries []string) error {
|
func (state *golistState) runContainsQueries(response *responseDeduper, queries []string) error {
|
||||||
for _, query := range queries {
|
for _, query := range queries {
|
||||||
// TODO(matloob): Do only one query per directory.
|
// TODO(matloob): Do only one query per directory.
|
||||||
@ -340,7 +264,7 @@ func (state *golistState) runContainsQueries(response *responseDeduper, queries
|
|||||||
|
|
||||||
// adhocPackage attempts to load or construct an ad-hoc package for a given
|
// adhocPackage attempts to load or construct an ad-hoc package for a given
|
||||||
// query, if the original call to the driver produced inadequate results.
|
// query, if the original call to the driver produced inadequate results.
|
||||||
func (state *golistState) adhocPackage(pattern, query string) (*driverResponse, error) {
|
func (state *golistState) adhocPackage(pattern, query string) (*DriverResponse, error) {
|
||||||
response, err := state.createDriverResponse(query)
|
response, err := state.createDriverResponse(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -431,7 +355,7 @@ func otherFiles(p *jsonPackage) [][]string {
|
|||||||
|
|
||||||
// createDriverResponse uses the "go list" command to expand the pattern
|
// createDriverResponse uses the "go list" command to expand the pattern
|
||||||
// words and return a response for the specified packages.
|
// words and return a response for the specified packages.
|
||||||
func (state *golistState) createDriverResponse(words ...string) (*driverResponse, error) {
|
func (state *golistState) createDriverResponse(words ...string) (*DriverResponse, error) {
|
||||||
// go list uses the following identifiers in ImportPath and Imports:
|
// go list uses the following identifiers in ImportPath and Imports:
|
||||||
//
|
//
|
||||||
// "p" -- importable package or main (command)
|
// "p" -- importable package or main (command)
|
||||||
@ -458,7 +382,7 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse
|
|||||||
pkgs := make(map[string]*Package)
|
pkgs := make(map[string]*Package)
|
||||||
additionalErrors := make(map[string][]Error)
|
additionalErrors := make(map[string][]Error)
|
||||||
// Decode the JSON and convert it to Package form.
|
// Decode the JSON and convert it to Package form.
|
||||||
response := &driverResponse{
|
response := &DriverResponse{
|
||||||
GoVersion: goVersion,
|
GoVersion: goVersion,
|
||||||
}
|
}
|
||||||
for dec := json.NewDecoder(buf); dec.More(); {
|
for dec := json.NewDecoder(buf); dec.More(); {
|
||||||
@ -916,6 +840,7 @@ func (state *golistState) cfgInvocation() gocommand.Invocation {
|
|||||||
Env: cfg.Env,
|
Env: cfg.Env,
|
||||||
Logf: cfg.Logf,
|
Logf: cfg.Logf,
|
||||||
WorkingDir: cfg.Dir,
|
WorkingDir: cfg.Dir,
|
||||||
|
Overlay: cfg.goListOverlayFile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -924,26 +849,6 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer,
|
|||||||
cfg := state.cfg
|
cfg := state.cfg
|
||||||
|
|
||||||
inv := state.cfgInvocation()
|
inv := state.cfgInvocation()
|
||||||
|
|
||||||
// For Go versions 1.16 and above, `go list` accepts overlays directly via
|
|
||||||
// the -overlay flag. Set it, if it's available.
|
|
||||||
//
|
|
||||||
// The check for "list" is not necessarily required, but we should avoid
|
|
||||||
// getting the go version if possible.
|
|
||||||
if verb == "list" {
|
|
||||||
goVersion, err := state.getGoVersion()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if goVersion >= 16 {
|
|
||||||
filename, cleanup, err := state.writeOverlays()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer cleanup()
|
|
||||||
inv.Overlay = filename
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inv.Verb = verb
|
inv.Verb = verb
|
||||||
inv.Args = args
|
inv.Args = args
|
||||||
gocmdRunner := cfg.gocmdRunner
|
gocmdRunner := cfg.gocmdRunner
|
||||||
@ -1090,67 +995,6 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer,
|
|||||||
return stdout, nil
|
return stdout, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OverlayJSON is the format overlay files are expected to be in.
|
|
||||||
// The Replace map maps from overlaid paths to replacement paths:
|
|
||||||
// the Go command will forward all reads trying to open
|
|
||||||
// each overlaid path to its replacement path, or consider the overlaid
|
|
||||||
// path not to exist if the replacement path is empty.
|
|
||||||
//
|
|
||||||
// From golang/go#39958.
|
|
||||||
type OverlayJSON struct {
|
|
||||||
Replace map[string]string `json:"replace,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeOverlays writes out files for go list's -overlay flag, as described
|
|
||||||
// above.
|
|
||||||
func (state *golistState) writeOverlays() (filename string, cleanup func(), err error) {
|
|
||||||
// Do nothing if there are no overlays in the config.
|
|
||||||
if len(state.cfg.Overlay) == 0 {
|
|
||||||
return "", func() {}, nil
|
|
||||||
}
|
|
||||||
dir, err := os.MkdirTemp("", "gopackages-*")
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
// The caller must clean up this directory, unless this function returns an
|
|
||||||
// error.
|
|
||||||
cleanup = func() {
|
|
||||||
os.RemoveAll(dir)
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
cleanup()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
overlays := map[string]string{}
|
|
||||||
for k, v := range state.cfg.Overlay {
|
|
||||||
// Create a unique filename for the overlaid files, to avoid
|
|
||||||
// creating nested directories.
|
|
||||||
noSeparator := strings.Join(strings.Split(filepath.ToSlash(k), "/"), "")
|
|
||||||
f, err := os.CreateTemp(dir, fmt.Sprintf("*-%s", noSeparator))
|
|
||||||
if err != nil {
|
|
||||||
return "", func() {}, err
|
|
||||||
}
|
|
||||||
if _, err := f.Write(v); err != nil {
|
|
||||||
return "", func() {}, err
|
|
||||||
}
|
|
||||||
if err := f.Close(); err != nil {
|
|
||||||
return "", func() {}, err
|
|
||||||
}
|
|
||||||
overlays[k] = f.Name()
|
|
||||||
}
|
|
||||||
b, err := json.Marshal(OverlayJSON{Replace: overlays})
|
|
||||||
if err != nil {
|
|
||||||
return "", func() {}, err
|
|
||||||
}
|
|
||||||
// Write out the overlay file that contains the filepath mappings.
|
|
||||||
filename = filepath.Join(dir, "overlay.json")
|
|
||||||
if err := os.WriteFile(filename, b, 0665); err != nil {
|
|
||||||
return "", func() {}, err
|
|
||||||
}
|
|
||||||
return filename, cleanup, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func containsGoFile(s []string) bool {
|
func containsGoFile(s []string) bool {
|
||||||
for _, f := range s {
|
for _, f := range s {
|
||||||
if strings.HasSuffix(f, ".go") {
|
if strings.HasSuffix(f, ".go") {
|
||||||
@ -1179,3 +1023,44 @@ func cmdDebugStr(cmd *exec.Cmd) string {
|
|||||||
}
|
}
|
||||||
return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], strings.Join(args, " "))
|
return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], strings.Join(args, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getSizesForArgs queries 'go list' for the appropriate
|
||||||
|
// Compiler and GOARCH arguments to pass to [types.SizesFor].
|
||||||
|
func getSizesForArgs(ctx context.Context, inv gocommand.Invocation, gocmdRunner *gocommand.Runner) (string, string, error) {
|
||||||
|
inv.Verb = "list"
|
||||||
|
inv.Args = []string{"-f", "{{context.GOARCH}} {{context.Compiler}}", "--", "unsafe"}
|
||||||
|
stdout, stderr, friendlyErr, rawErr := gocmdRunner.RunRaw(ctx, inv)
|
||||||
|
var goarch, compiler string
|
||||||
|
if rawErr != nil {
|
||||||
|
rawErrMsg := rawErr.Error()
|
||||||
|
if strings.Contains(rawErrMsg, "cannot find main module") ||
|
||||||
|
strings.Contains(rawErrMsg, "go.mod file not found") {
|
||||||
|
// User's running outside of a module.
|
||||||
|
// All bets are off. Get GOARCH and guess compiler is gc.
|
||||||
|
// TODO(matloob): Is this a problem in practice?
|
||||||
|
inv.Verb = "env"
|
||||||
|
inv.Args = []string{"GOARCH"}
|
||||||
|
envout, enverr := gocmdRunner.Run(ctx, inv)
|
||||||
|
if enverr != nil {
|
||||||
|
return "", "", enverr
|
||||||
|
}
|
||||||
|
goarch = strings.TrimSpace(envout.String())
|
||||||
|
compiler = "gc"
|
||||||
|
} else if friendlyErr != nil {
|
||||||
|
return "", "", friendlyErr
|
||||||
|
} else {
|
||||||
|
// This should be unreachable, but be defensive
|
||||||
|
// in case RunRaw's error results are inconsistent.
|
||||||
|
return "", "", rawErr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fields := strings.Fields(stdout.String())
|
||||||
|
if len(fields) < 2 {
|
||||||
|
return "", "", fmt.Errorf("could not parse GOARCH and Go compiler in format \"<GOARCH> <compiler>\":\nstdout: <<%s>>\nstderr: <<%s>>",
|
||||||
|
stdout.String(), stderr.String())
|
||||||
|
}
|
||||||
|
goarch = fields[0]
|
||||||
|
compiler = fields[1]
|
||||||
|
}
|
||||||
|
return compiler, goarch, nil
|
||||||
|
}
|
||||||
|
492
vendor/golang.org/x/tools/go/packages/golist_overlay.go
generated
vendored
492
vendor/golang.org/x/tools/go/packages/golist_overlay.go
generated
vendored
@ -6,314 +6,11 @@ package packages
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"go/parser"
|
|
||||||
"go/token"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/tools/internal/gocommand"
|
"golang.org/x/tools/internal/gocommand"
|
||||||
)
|
)
|
||||||
|
|
||||||
// processGolistOverlay provides rudimentary support for adding
|
|
||||||
// files that don't exist on disk to an overlay. The results can be
|
|
||||||
// sometimes incorrect.
|
|
||||||
// TODO(matloob): Handle unsupported cases, including the following:
|
|
||||||
// - determining the correct package to add given a new import path
|
|
||||||
func (state *golistState) processGolistOverlay(response *responseDeduper) (modifiedPkgs, needPkgs []string, err error) {
|
|
||||||
havePkgs := make(map[string]string) // importPath -> non-test package ID
|
|
||||||
needPkgsSet := make(map[string]bool)
|
|
||||||
modifiedPkgsSet := make(map[string]bool)
|
|
||||||
|
|
||||||
pkgOfDir := make(map[string][]*Package)
|
|
||||||
for _, pkg := range response.dr.Packages {
|
|
||||||
// This is an approximation of import path to id. This can be
|
|
||||||
// wrong for tests, vendored packages, and a number of other cases.
|
|
||||||
havePkgs[pkg.PkgPath] = pkg.ID
|
|
||||||
dir, err := commonDir(pkg.GoFiles)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
if dir != "" {
|
|
||||||
pkgOfDir[dir] = append(pkgOfDir[dir], pkg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no new imports are added, it is safe to avoid loading any needPkgs.
|
|
||||||
// Otherwise, it's hard to tell which package is actually being loaded
|
|
||||||
// (due to vendoring) and whether any modified package will show up
|
|
||||||
// in the transitive set of dependencies (because new imports are added,
|
|
||||||
// potentially modifying the transitive set of dependencies).
|
|
||||||
var overlayAddsImports bool
|
|
||||||
|
|
||||||
// If both a package and its test package are created by the overlay, we
|
|
||||||
// need the real package first. Process all non-test files before test
|
|
||||||
// files, and make the whole process deterministic while we're at it.
|
|
||||||
var overlayFiles []string
|
|
||||||
for opath := range state.cfg.Overlay {
|
|
||||||
overlayFiles = append(overlayFiles, opath)
|
|
||||||
}
|
|
||||||
sort.Slice(overlayFiles, func(i, j int) bool {
|
|
||||||
iTest := strings.HasSuffix(overlayFiles[i], "_test.go")
|
|
||||||
jTest := strings.HasSuffix(overlayFiles[j], "_test.go")
|
|
||||||
if iTest != jTest {
|
|
||||||
return !iTest // non-tests are before tests.
|
|
||||||
}
|
|
||||||
return overlayFiles[i] < overlayFiles[j]
|
|
||||||
})
|
|
||||||
for _, opath := range overlayFiles {
|
|
||||||
contents := state.cfg.Overlay[opath]
|
|
||||||
base := filepath.Base(opath)
|
|
||||||
dir := filepath.Dir(opath)
|
|
||||||
var pkg *Package // if opath belongs to both a package and its test variant, this will be the test variant
|
|
||||||
var testVariantOf *Package // if opath is a test file, this is the package it is testing
|
|
||||||
var fileExists bool
|
|
||||||
isTestFile := strings.HasSuffix(opath, "_test.go")
|
|
||||||
pkgName, ok := extractPackageName(opath, contents)
|
|
||||||
if !ok {
|
|
||||||
// Don't bother adding a file that doesn't even have a parsable package statement
|
|
||||||
// to the overlay.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// If all the overlay files belong to a different package, change the
|
|
||||||
// package name to that package.
|
|
||||||
maybeFixPackageName(pkgName, isTestFile, pkgOfDir[dir])
|
|
||||||
nextPackage:
|
|
||||||
for _, p := range response.dr.Packages {
|
|
||||||
if pkgName != p.Name && p.ID != "command-line-arguments" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, f := range p.GoFiles {
|
|
||||||
if !sameFile(filepath.Dir(f), dir) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Make sure to capture information on the package's test variant, if needed.
|
|
||||||
if isTestFile && !hasTestFiles(p) {
|
|
||||||
// TODO(matloob): Are there packages other than the 'production' variant
|
|
||||||
// of a package that this can match? This shouldn't match the test main package
|
|
||||||
// because the file is generated in another directory.
|
|
||||||
testVariantOf = p
|
|
||||||
continue nextPackage
|
|
||||||
} else if !isTestFile && hasTestFiles(p) {
|
|
||||||
// We're examining a test variant, but the overlaid file is
|
|
||||||
// a non-test file. Because the overlay implementation
|
|
||||||
// (currently) only adds a file to one package, skip this
|
|
||||||
// package, so that we can add the file to the production
|
|
||||||
// variant of the package. (https://golang.org/issue/36857
|
|
||||||
// tracks handling overlays on both the production and test
|
|
||||||
// variant of a package).
|
|
||||||
continue nextPackage
|
|
||||||
}
|
|
||||||
if pkg != nil && p != pkg && pkg.PkgPath == p.PkgPath {
|
|
||||||
// We have already seen the production version of the
|
|
||||||
// for which p is a test variant.
|
|
||||||
if hasTestFiles(p) {
|
|
||||||
testVariantOf = pkg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pkg = p
|
|
||||||
if filepath.Base(f) == base {
|
|
||||||
fileExists = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// The overlay could have included an entirely new package or an
|
|
||||||
// ad-hoc package. An ad-hoc package is one that we have manually
|
|
||||||
// constructed from inadequate `go list` results for a file= query.
|
|
||||||
// It will have the ID command-line-arguments.
|
|
||||||
if pkg == nil || pkg.ID == "command-line-arguments" {
|
|
||||||
// Try to find the module or gopath dir the file is contained in.
|
|
||||||
// Then for modules, add the module opath to the beginning.
|
|
||||||
pkgPath, ok, err := state.getPkgPath(dir)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
var forTest string // only set for x tests
|
|
||||||
isXTest := strings.HasSuffix(pkgName, "_test")
|
|
||||||
if isXTest {
|
|
||||||
forTest = pkgPath
|
|
||||||
pkgPath += "_test"
|
|
||||||
}
|
|
||||||
id := pkgPath
|
|
||||||
if isTestFile {
|
|
||||||
if isXTest {
|
|
||||||
id = fmt.Sprintf("%s [%s.test]", pkgPath, forTest)
|
|
||||||
} else {
|
|
||||||
id = fmt.Sprintf("%s [%s.test]", pkgPath, pkgPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if pkg != nil {
|
|
||||||
// TODO(rstambler): We should change the package's path and ID
|
|
||||||
// here. The only issue is that this messes with the roots.
|
|
||||||
} else {
|
|
||||||
// Try to reclaim a package with the same ID, if it exists in the response.
|
|
||||||
for _, p := range response.dr.Packages {
|
|
||||||
if reclaimPackage(p, id, opath, contents) {
|
|
||||||
pkg = p
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Otherwise, create a new package.
|
|
||||||
if pkg == nil {
|
|
||||||
pkg = &Package{
|
|
||||||
PkgPath: pkgPath,
|
|
||||||
ID: id,
|
|
||||||
Name: pkgName,
|
|
||||||
Imports: make(map[string]*Package),
|
|
||||||
}
|
|
||||||
response.addPackage(pkg)
|
|
||||||
havePkgs[pkg.PkgPath] = id
|
|
||||||
// Add the production package's sources for a test variant.
|
|
||||||
if isTestFile && !isXTest && testVariantOf != nil {
|
|
||||||
pkg.GoFiles = append(pkg.GoFiles, testVariantOf.GoFiles...)
|
|
||||||
pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, testVariantOf.CompiledGoFiles...)
|
|
||||||
// Add the package under test and its imports to the test variant.
|
|
||||||
pkg.forTest = testVariantOf.PkgPath
|
|
||||||
for k, v := range testVariantOf.Imports {
|
|
||||||
pkg.Imports[k] = &Package{ID: v.ID}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isXTest {
|
|
||||||
pkg.forTest = forTest
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !fileExists {
|
|
||||||
pkg.GoFiles = append(pkg.GoFiles, opath)
|
|
||||||
// TODO(matloob): Adding the file to CompiledGoFiles can exhibit the wrong behavior
|
|
||||||
// if the file will be ignored due to its build tags.
|
|
||||||
pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, opath)
|
|
||||||
modifiedPkgsSet[pkg.ID] = true
|
|
||||||
}
|
|
||||||
imports, err := extractImports(opath, contents)
|
|
||||||
if err != nil {
|
|
||||||
// Let the parser or type checker report errors later.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, imp := range imports {
|
|
||||||
// TODO(rstambler): If the package is an x test and the import has
|
|
||||||
// a test variant, make sure to replace it.
|
|
||||||
if _, found := pkg.Imports[imp]; found {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
overlayAddsImports = true
|
|
||||||
id, ok := havePkgs[imp]
|
|
||||||
if !ok {
|
|
||||||
var err error
|
|
||||||
id, err = state.resolveImport(dir, imp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pkg.Imports[imp] = &Package{ID: id}
|
|
||||||
// Add dependencies to the non-test variant version of this package as well.
|
|
||||||
if testVariantOf != nil {
|
|
||||||
testVariantOf.Imports[imp] = &Package{ID: id}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// toPkgPath guesses the package path given the id.
|
|
||||||
toPkgPath := func(sourceDir, id string) (string, error) {
|
|
||||||
if i := strings.IndexByte(id, ' '); i >= 0 {
|
|
||||||
return state.resolveImport(sourceDir, id[:i])
|
|
||||||
}
|
|
||||||
return state.resolveImport(sourceDir, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that new packages have been created, do another pass to determine
|
|
||||||
// the new set of missing packages.
|
|
||||||
for _, pkg := range response.dr.Packages {
|
|
||||||
for _, imp := range pkg.Imports {
|
|
||||||
if len(pkg.GoFiles) == 0 {
|
|
||||||
return nil, nil, fmt.Errorf("cannot resolve imports for package %q with no Go files", pkg.PkgPath)
|
|
||||||
}
|
|
||||||
pkgPath, err := toPkgPath(filepath.Dir(pkg.GoFiles[0]), imp.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
if _, ok := havePkgs[pkgPath]; !ok {
|
|
||||||
needPkgsSet[pkgPath] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if overlayAddsImports {
|
|
||||||
needPkgs = make([]string, 0, len(needPkgsSet))
|
|
||||||
for pkg := range needPkgsSet {
|
|
||||||
needPkgs = append(needPkgs, pkg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
modifiedPkgs = make([]string, 0, len(modifiedPkgsSet))
|
|
||||||
for pkg := range modifiedPkgsSet {
|
|
||||||
modifiedPkgs = append(modifiedPkgs, pkg)
|
|
||||||
}
|
|
||||||
return modifiedPkgs, needPkgs, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolveImport finds the ID of a package given its import path.
|
|
||||||
// In particular, it will find the right vendored copy when in GOPATH mode.
|
|
||||||
func (state *golistState) resolveImport(sourceDir, importPath string) (string, error) {
|
|
||||||
env, err := state.getEnv()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if env["GOMOD"] != "" {
|
|
||||||
return importPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
searchDir := sourceDir
|
|
||||||
for {
|
|
||||||
vendorDir := filepath.Join(searchDir, "vendor")
|
|
||||||
exists, ok := state.vendorDirs[vendorDir]
|
|
||||||
if !ok {
|
|
||||||
info, err := os.Stat(vendorDir)
|
|
||||||
exists = err == nil && info.IsDir()
|
|
||||||
state.vendorDirs[vendorDir] = exists
|
|
||||||
}
|
|
||||||
|
|
||||||
if exists {
|
|
||||||
vendoredPath := filepath.Join(vendorDir, importPath)
|
|
||||||
if info, err := os.Stat(vendoredPath); err == nil && info.IsDir() {
|
|
||||||
// We should probably check for .go files here, but shame on anyone who fools us.
|
|
||||||
path, ok, err := state.getPkgPath(vendoredPath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We know we've hit the top of the filesystem when we Dir / and get /,
|
|
||||||
// or C:\ and get C:\, etc.
|
|
||||||
next := filepath.Dir(searchDir)
|
|
||||||
if next == searchDir {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
searchDir = next
|
|
||||||
}
|
|
||||||
return importPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasTestFiles(p *Package) bool {
|
|
||||||
for _, f := range p.GoFiles {
|
|
||||||
if strings.HasSuffix(f, "_test.go") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// determineRootDirs returns a mapping from absolute directories that could
|
// determineRootDirs returns a mapping from absolute directories that could
|
||||||
// contain code to their corresponding import path prefixes.
|
// contain code to their corresponding import path prefixes.
|
||||||
func (state *golistState) determineRootDirs() (map[string]string, error) {
|
func (state *golistState) determineRootDirs() (map[string]string, error) {
|
||||||
@ -384,192 +81,3 @@ func (state *golistState) determineRootDirsGOPATH() (map[string]string, error) {
|
|||||||
}
|
}
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractImports(filename string, contents []byte) ([]string, error) {
|
|
||||||
f, err := parser.ParseFile(token.NewFileSet(), filename, contents, parser.ImportsOnly) // TODO(matloob): reuse fileset?
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var res []string
|
|
||||||
for _, imp := range f.Imports {
|
|
||||||
quotedPath := imp.Path.Value
|
|
||||||
path, err := strconv.Unquote(quotedPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
res = append(res, path)
|
|
||||||
}
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// reclaimPackage attempts to reuse a package that failed to load in an overlay.
|
|
||||||
//
|
|
||||||
// If the package has errors and has no Name, GoFiles, or Imports,
|
|
||||||
// then it's possible that it doesn't yet exist on disk.
|
|
||||||
func reclaimPackage(pkg *Package, id string, filename string, contents []byte) bool {
|
|
||||||
// TODO(rstambler): Check the message of the actual error?
|
|
||||||
// It differs between $GOPATH and module mode.
|
|
||||||
if pkg.ID != id {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(pkg.Errors) != 1 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if pkg.Name != "" || pkg.ExportFile != "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(pkg.GoFiles) > 0 || len(pkg.CompiledGoFiles) > 0 || len(pkg.OtherFiles) > 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(pkg.Imports) > 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
pkgName, ok := extractPackageName(filename, contents)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
pkg.Name = pkgName
|
|
||||||
pkg.Errors = nil
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractPackageName(filename string, contents []byte) (string, bool) {
|
|
||||||
// TODO(rstambler): Check the message of the actual error?
|
|
||||||
// It differs between $GOPATH and module mode.
|
|
||||||
f, err := parser.ParseFile(token.NewFileSet(), filename, contents, parser.PackageClauseOnly) // TODO(matloob): reuse fileset?
|
|
||||||
if err != nil {
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
return f.Name.Name, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// commonDir returns the directory that all files are in, "" if files is empty,
|
|
||||||
// or an error if they aren't in the same directory.
|
|
||||||
func commonDir(files []string) (string, error) {
|
|
||||||
seen := make(map[string]bool)
|
|
||||||
for _, f := range files {
|
|
||||||
seen[filepath.Dir(f)] = true
|
|
||||||
}
|
|
||||||
if len(seen) > 1 {
|
|
||||||
return "", fmt.Errorf("files (%v) are in more than one directory: %v", files, seen)
|
|
||||||
}
|
|
||||||
for k := range seen {
|
|
||||||
// seen has only one element; return it.
|
|
||||||
return k, nil
|
|
||||||
}
|
|
||||||
return "", nil // no files
|
|
||||||
}
|
|
||||||
|
|
||||||
// It is possible that the files in the disk directory dir have a different package
|
|
||||||
// name from newName, which is deduced from the overlays. If they all have a different
|
|
||||||
// package name, and they all have the same package name, then that name becomes
|
|
||||||
// the package name.
|
|
||||||
// It returns true if it changes the package name, false otherwise.
|
|
||||||
func maybeFixPackageName(newName string, isTestFile bool, pkgsOfDir []*Package) {
|
|
||||||
names := make(map[string]int)
|
|
||||||
for _, p := range pkgsOfDir {
|
|
||||||
names[p.Name]++
|
|
||||||
}
|
|
||||||
if len(names) != 1 {
|
|
||||||
// some files are in different packages
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var oldName string
|
|
||||||
for k := range names {
|
|
||||||
oldName = k
|
|
||||||
}
|
|
||||||
if newName == oldName {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// We might have a case where all of the package names in the directory are
|
|
||||||
// the same, but the overlay file is for an x test, which belongs to its
|
|
||||||
// own package. If the x test does not yet exist on disk, we may not yet
|
|
||||||
// have its package name on disk, but we should not rename the packages.
|
|
||||||
//
|
|
||||||
// We use a heuristic to determine if this file belongs to an x test:
|
|
||||||
// The test file should have a package name whose package name has a _test
|
|
||||||
// suffix or looks like "newName_test".
|
|
||||||
maybeXTest := strings.HasPrefix(oldName+"_test", newName) || strings.HasSuffix(newName, "_test")
|
|
||||||
if isTestFile && maybeXTest {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, p := range pkgsOfDir {
|
|
||||||
p.Name = newName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is copy-pasted from
|
|
||||||
// https://github.com/golang/go/blob/9706f510a5e2754595d716bd64be8375997311fb/src/cmd/go/internal/search/search.go#L360.
|
|
||||||
// It should be deleted when we remove support for overlays from go/packages.
|
|
||||||
//
|
|
||||||
// NOTE: This does not handle any ./... or ./ style queries, as this function
|
|
||||||
// doesn't know the working directory.
|
|
||||||
//
|
|
||||||
// matchPattern(pattern)(name) reports whether
|
|
||||||
// name matches pattern. Pattern is a limited glob
|
|
||||||
// pattern in which '...' means 'any string' and there
|
|
||||||
// is no other special syntax.
|
|
||||||
// Unfortunately, there are two special cases. Quoting "go help packages":
|
|
||||||
//
|
|
||||||
// First, /... at the end of the pattern can match an empty string,
|
|
||||||
// so that net/... matches both net and packages in its subdirectories, like net/http.
|
|
||||||
// Second, any slash-separated pattern element containing a wildcard never
|
|
||||||
// participates in a match of the "vendor" element in the path of a vendored
|
|
||||||
// package, so that ./... does not match packages in subdirectories of
|
|
||||||
// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do.
|
|
||||||
// Note, however, that a directory named vendor that itself contains code
|
|
||||||
// is not a vendored package: cmd/vendor would be a command named vendor,
|
|
||||||
// and the pattern cmd/... matches it.
|
|
||||||
func matchPattern(pattern string) func(name string) bool {
|
|
||||||
// Convert pattern to regular expression.
|
|
||||||
// The strategy for the trailing /... is to nest it in an explicit ? expression.
|
|
||||||
// The strategy for the vendor exclusion is to change the unmatchable
|
|
||||||
// vendor strings to a disallowed code point (vendorChar) and to use
|
|
||||||
// "(anything but that codepoint)*" as the implementation of the ... wildcard.
|
|
||||||
// This is a bit complicated but the obvious alternative,
|
|
||||||
// namely a hand-written search like in most shell glob matchers,
|
|
||||||
// is too easy to make accidentally exponential.
|
|
||||||
// Using package regexp guarantees linear-time matching.
|
|
||||||
|
|
||||||
const vendorChar = "\x00"
|
|
||||||
|
|
||||||
if strings.Contains(pattern, vendorChar) {
|
|
||||||
return func(name string) bool { return false }
|
|
||||||
}
|
|
||||||
|
|
||||||
re := regexp.QuoteMeta(pattern)
|
|
||||||
re = replaceVendor(re, vendorChar)
|
|
||||||
switch {
|
|
||||||
case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`):
|
|
||||||
re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)`
|
|
||||||
case re == vendorChar+`/\.\.\.`:
|
|
||||||
re = `(/vendor|/` + vendorChar + `/\.\.\.)`
|
|
||||||
case strings.HasSuffix(re, `/\.\.\.`):
|
|
||||||
re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?`
|
|
||||||
}
|
|
||||||
re = strings.ReplaceAll(re, `\.\.\.`, `[^`+vendorChar+`]*`)
|
|
||||||
|
|
||||||
reg := regexp.MustCompile(`^` + re + `$`)
|
|
||||||
|
|
||||||
return func(name string) bool {
|
|
||||||
if strings.Contains(name, vendorChar) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return reg.MatchString(replaceVendor(name, vendorChar))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// replaceVendor returns the result of replacing
|
|
||||||
// non-trailing vendor path elements in x with repl.
|
|
||||||
func replaceVendor(x, repl string) string {
|
|
||||||
if !strings.Contains(x, "vendor") {
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
elem := strings.Split(x, "/")
|
|
||||||
for i := 0; i < len(elem)-1; i++ {
|
|
||||||
if elem[i] == "vendor" {
|
|
||||||
elem[i] = repl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.Join(elem, "/")
|
|
||||||
}
|
|
||||||
|
71
vendor/golang.org/x/tools/go/packages/loadmode_string.go
generated
vendored
71
vendor/golang.org/x/tools/go/packages/loadmode_string.go
generated
vendored
@ -9,49 +9,46 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var allModes = []LoadMode{
|
var modes = [...]struct {
|
||||||
NeedName,
|
mode LoadMode
|
||||||
NeedFiles,
|
name string
|
||||||
NeedCompiledGoFiles,
|
}{
|
||||||
NeedImports,
|
{NeedName, "NeedName"},
|
||||||
NeedDeps,
|
{NeedFiles, "NeedFiles"},
|
||||||
NeedExportFile,
|
{NeedCompiledGoFiles, "NeedCompiledGoFiles"},
|
||||||
NeedTypes,
|
{NeedImports, "NeedImports"},
|
||||||
NeedSyntax,
|
{NeedDeps, "NeedDeps"},
|
||||||
NeedTypesInfo,
|
{NeedExportFile, "NeedExportFile"},
|
||||||
NeedTypesSizes,
|
{NeedTypes, "NeedTypes"},
|
||||||
|
{NeedSyntax, "NeedSyntax"},
|
||||||
|
{NeedTypesInfo, "NeedTypesInfo"},
|
||||||
|
{NeedTypesSizes, "NeedTypesSizes"},
|
||||||
|
{NeedModule, "NeedModule"},
|
||||||
|
{NeedEmbedFiles, "NeedEmbedFiles"},
|
||||||
|
{NeedEmbedPatterns, "NeedEmbedPatterns"},
|
||||||
}
|
}
|
||||||
|
|
||||||
var modeStrings = []string{
|
func (mode LoadMode) String() string {
|
||||||
"NeedName",
|
if mode == 0 {
|
||||||
"NeedFiles",
|
|
||||||
"NeedCompiledGoFiles",
|
|
||||||
"NeedImports",
|
|
||||||
"NeedDeps",
|
|
||||||
"NeedExportFile",
|
|
||||||
"NeedTypes",
|
|
||||||
"NeedSyntax",
|
|
||||||
"NeedTypesInfo",
|
|
||||||
"NeedTypesSizes",
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod LoadMode) String() string {
|
|
||||||
m := mod
|
|
||||||
if m == 0 {
|
|
||||||
return "LoadMode(0)"
|
return "LoadMode(0)"
|
||||||
}
|
}
|
||||||
var out []string
|
var out []string
|
||||||
for i, x := range allModes {
|
// named bits
|
||||||
if x > m {
|
for _, item := range modes {
|
||||||
break
|
if (mode & item.mode) != 0 {
|
||||||
}
|
mode ^= item.mode
|
||||||
if (m & x) != 0 {
|
out = append(out, item.name)
|
||||||
out = append(out, modeStrings[i])
|
|
||||||
m = m ^ x
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m != 0 {
|
// unnamed residue
|
||||||
out = append(out, "Unknown")
|
if mode != 0 {
|
||||||
|
if out == nil {
|
||||||
|
return fmt.Sprintf("LoadMode(%#x)", int(mode))
|
||||||
|
}
|
||||||
|
out = append(out, fmt.Sprintf("%#x", int(mode)))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("LoadMode(%s)", strings.Join(out, "|"))
|
if len(out) == 1 {
|
||||||
|
return out[0]
|
||||||
|
}
|
||||||
|
return "(" + strings.Join(out, "|") + ")"
|
||||||
}
|
}
|
||||||
|
492
vendor/golang.org/x/tools/go/packages/packages.go
generated
vendored
492
vendor/golang.org/x/tools/go/packages/packages.go
generated
vendored
@ -9,6 +9,7 @@ package packages
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
@ -24,20 +25,31 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"golang.org/x/tools/go/gcexportdata"
|
"golang.org/x/tools/go/gcexportdata"
|
||||||
"golang.org/x/tools/internal/gocommand"
|
"golang.org/x/tools/internal/gocommand"
|
||||||
"golang.org/x/tools/internal/packagesinternal"
|
"golang.org/x/tools/internal/packagesinternal"
|
||||||
"golang.org/x/tools/internal/typeparams"
|
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A LoadMode controls the amount of detail to return when loading.
|
// A LoadMode controls the amount of detail to return when loading.
|
||||||
// The bits below can be combined to specify which fields should be
|
// The bits below can be combined to specify which fields should be
|
||||||
// filled in the result packages.
|
// filled in the result packages.
|
||||||
|
//
|
||||||
// The zero value is a special case, equivalent to combining
|
// The zero value is a special case, equivalent to combining
|
||||||
// the NeedName, NeedFiles, and NeedCompiledGoFiles bits.
|
// the NeedName, NeedFiles, and NeedCompiledGoFiles bits.
|
||||||
|
//
|
||||||
// ID and Errors (if present) will always be filled.
|
// ID and Errors (if present) will always be filled.
|
||||||
// Load may return more information than requested.
|
// [Load] may return more information than requested.
|
||||||
|
//
|
||||||
|
// Unfortunately there are a number of open bugs related to
|
||||||
|
// interactions among the LoadMode bits:
|
||||||
|
// - https://github.com/golang/go/issues/56633
|
||||||
|
// - https://github.com/golang/go/issues/56677
|
||||||
|
// - https://github.com/golang/go/issues/58726
|
||||||
|
// - https://github.com/golang/go/issues/63517
|
||||||
type LoadMode int
|
type LoadMode int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -63,7 +75,7 @@ const (
|
|||||||
// NeedTypes adds Types, Fset, and IllTyped.
|
// NeedTypes adds Types, Fset, and IllTyped.
|
||||||
NeedTypes
|
NeedTypes
|
||||||
|
|
||||||
// NeedSyntax adds Syntax.
|
// NeedSyntax adds Syntax and Fset.
|
||||||
NeedSyntax
|
NeedSyntax
|
||||||
|
|
||||||
// NeedTypesInfo adds TypesInfo.
|
// NeedTypesInfo adds TypesInfo.
|
||||||
@ -91,25 +103,37 @@ const (
|
|||||||
|
|
||||||
// NeedEmbedPatterns adds EmbedPatterns.
|
// NeedEmbedPatterns adds EmbedPatterns.
|
||||||
NeedEmbedPatterns
|
NeedEmbedPatterns
|
||||||
|
|
||||||
|
// Be sure to update loadmode_string.go when adding new items!
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// LoadFiles loads the name and file names for the initial packages.
|
||||||
|
//
|
||||||
// Deprecated: LoadFiles exists for historical compatibility
|
// Deprecated: LoadFiles exists for historical compatibility
|
||||||
// and should not be used. Please directly specify the needed fields using the Need values.
|
// and should not be used. Please directly specify the needed fields using the Need values.
|
||||||
LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles
|
LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles
|
||||||
|
|
||||||
|
// LoadImports loads the name, file names, and import mapping for the initial packages.
|
||||||
|
//
|
||||||
// Deprecated: LoadImports exists for historical compatibility
|
// Deprecated: LoadImports exists for historical compatibility
|
||||||
// and should not be used. Please directly specify the needed fields using the Need values.
|
// and should not be used. Please directly specify the needed fields using the Need values.
|
||||||
LoadImports = LoadFiles | NeedImports
|
LoadImports = LoadFiles | NeedImports
|
||||||
|
|
||||||
|
// LoadTypes loads exported type information for the initial packages.
|
||||||
|
//
|
||||||
// Deprecated: LoadTypes exists for historical compatibility
|
// Deprecated: LoadTypes exists for historical compatibility
|
||||||
// and should not be used. Please directly specify the needed fields using the Need values.
|
// and should not be used. Please directly specify the needed fields using the Need values.
|
||||||
LoadTypes = LoadImports | NeedTypes | NeedTypesSizes
|
LoadTypes = LoadImports | NeedTypes | NeedTypesSizes
|
||||||
|
|
||||||
|
// LoadSyntax loads typed syntax for the initial packages.
|
||||||
|
//
|
||||||
// Deprecated: LoadSyntax exists for historical compatibility
|
// Deprecated: LoadSyntax exists for historical compatibility
|
||||||
// and should not be used. Please directly specify the needed fields using the Need values.
|
// and should not be used. Please directly specify the needed fields using the Need values.
|
||||||
LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo
|
LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo
|
||||||
|
|
||||||
|
// LoadAllSyntax loads typed syntax for the initial packages and all dependencies.
|
||||||
|
//
|
||||||
// Deprecated: LoadAllSyntax exists for historical compatibility
|
// Deprecated: LoadAllSyntax exists for historical compatibility
|
||||||
// and should not be used. Please directly specify the needed fields using the Need values.
|
// and should not be used. Please directly specify the needed fields using the Need values.
|
||||||
LoadAllSyntax = LoadSyntax | NeedDeps
|
LoadAllSyntax = LoadSyntax | NeedDeps
|
||||||
@ -120,15 +144,21 @@ const (
|
|||||||
|
|
||||||
// A Config specifies details about how packages should be loaded.
|
// A Config specifies details about how packages should be loaded.
|
||||||
// The zero value is a valid configuration.
|
// The zero value is a valid configuration.
|
||||||
|
//
|
||||||
// Calls to Load do not modify this struct.
|
// Calls to Load do not modify this struct.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): #67702: this is currently false: in fact,
|
||||||
|
// calls to [Load] do not modify the public fields of this struct, but
|
||||||
|
// may modify hidden fields, so concurrent calls to [Load] must not
|
||||||
|
// use the same Config. But perhaps we should reestablish the
|
||||||
|
// documented invariant.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// Mode controls the level of information returned for each package.
|
// Mode controls the level of information returned for each package.
|
||||||
Mode LoadMode
|
Mode LoadMode
|
||||||
|
|
||||||
// Context specifies the context for the load operation.
|
// Context specifies the context for the load operation.
|
||||||
// If the context is cancelled, the loader may stop early
|
// Cancelling the context may cause [Load] to abort and
|
||||||
// and return an ErrCancelled error.
|
// return an error.
|
||||||
// If Context is nil, the load cannot be cancelled.
|
|
||||||
Context context.Context
|
Context context.Context
|
||||||
|
|
||||||
// Logf is the logger for the config.
|
// Logf is the logger for the config.
|
||||||
@ -197,95 +227,209 @@ type Config struct {
|
|||||||
// setting Tests may have no effect.
|
// setting Tests may have no effect.
|
||||||
Tests bool
|
Tests bool
|
||||||
|
|
||||||
// Overlay provides a mapping of absolute file paths to file contents.
|
// Overlay is a mapping from absolute file paths to file contents.
|
||||||
// If the file with the given path already exists, the parser will use the
|
|
||||||
// alternative file contents provided by the map.
|
|
||||||
//
|
//
|
||||||
// Overlays provide incomplete support for when a given file doesn't
|
// For each map entry, [Load] uses the alternative file
|
||||||
// already exist on disk. See the package doc above for more details.
|
// contents provided by the overlay mapping instead of reading
|
||||||
|
// from the file system. This mechanism can be used to enable
|
||||||
|
// editor-integrated tools to correctly analyze the contents
|
||||||
|
// of modified but unsaved buffers, for example.
|
||||||
|
//
|
||||||
|
// The overlay mapping is passed to the build system's driver
|
||||||
|
// (see "The driver protocol") so that it too can report
|
||||||
|
// consistent package metadata about unsaved files. However,
|
||||||
|
// drivers may vary in their level of support for overlays.
|
||||||
Overlay map[string][]byte
|
Overlay map[string][]byte
|
||||||
}
|
|
||||||
|
|
||||||
// driver is the type for functions that query the build system for the
|
// goListOverlayFile is the JSON file that encodes the Overlay
|
||||||
// packages named by the patterns.
|
// mapping, used by 'go list -overlay=...'
|
||||||
type driver func(cfg *Config, patterns ...string) (*driverResponse, error)
|
goListOverlayFile string
|
||||||
|
|
||||||
// driverResponse contains the results for a driver query.
|
|
||||||
type driverResponse struct {
|
|
||||||
// NotHandled is returned if the request can't be handled by the current
|
|
||||||
// driver. If an external driver returns a response with NotHandled, the
|
|
||||||
// rest of the driverResponse is ignored, and go/packages will fallback
|
|
||||||
// to the next driver. If go/packages is extended in the future to support
|
|
||||||
// lists of multiple drivers, go/packages will fall back to the next driver.
|
|
||||||
NotHandled bool
|
|
||||||
|
|
||||||
// Compiler and Arch are the arguments pass of types.SizesFor
|
|
||||||
// to get a types.Sizes to use when type checking.
|
|
||||||
Compiler string
|
|
||||||
Arch string
|
|
||||||
|
|
||||||
// Roots is the set of package IDs that make up the root packages.
|
|
||||||
// We have to encode this separately because when we encode a single package
|
|
||||||
// we cannot know if it is one of the roots as that requires knowledge of the
|
|
||||||
// graph it is part of.
|
|
||||||
Roots []string `json:",omitempty"`
|
|
||||||
|
|
||||||
// Packages is the full set of packages in the graph.
|
|
||||||
// The packages are not connected into a graph.
|
|
||||||
// The Imports if populated will be stubs that only have their ID set.
|
|
||||||
// Imports will be connected and then type and syntax information added in a
|
|
||||||
// later pass (see refine).
|
|
||||||
Packages []*Package
|
|
||||||
|
|
||||||
// GoVersion is the minor version number used by the driver
|
|
||||||
// (e.g. the go command on the PATH) when selecting .go files.
|
|
||||||
// Zero means unknown.
|
|
||||||
GoVersion int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load loads and returns the Go packages named by the given patterns.
|
// Load loads and returns the Go packages named by the given patterns.
|
||||||
//
|
//
|
||||||
// Config specifies loading options;
|
// The cfg parameter specifies loading options; nil behaves the same as an empty [Config].
|
||||||
// nil behaves the same as an empty Config.
|
|
||||||
//
|
//
|
||||||
// Load returns an error if any of the patterns was invalid
|
// The [Config.Mode] field is a set of bits that determine what kinds
|
||||||
// as defined by the underlying build system.
|
// of information should be computed and returned. Modes that require
|
||||||
|
// more information tend to be slower. See [LoadMode] for details
|
||||||
|
// and important caveats. Its zero value is equivalent to
|
||||||
|
// [NeedName] | [NeedFiles] | [NeedCompiledGoFiles].
|
||||||
|
//
|
||||||
|
// Each call to Load returns a new set of [Package] instances.
|
||||||
|
// The Packages and their Imports form a directed acyclic graph.
|
||||||
|
//
|
||||||
|
// If the [NeedTypes] mode flag was set, each call to Load uses a new
|
||||||
|
// [types.Importer], so [types.Object] and [types.Type] values from
|
||||||
|
// different calls to Load must not be mixed as they will have
|
||||||
|
// inconsistent notions of type identity.
|
||||||
|
//
|
||||||
|
// If any of the patterns was invalid as defined by the
|
||||||
|
// underlying build system, Load returns an error.
|
||||||
// It may return an empty list of packages without an error,
|
// It may return an empty list of packages without an error,
|
||||||
// for instance for an empty expansion of a valid wildcard.
|
// for instance for an empty expansion of a valid wildcard.
|
||||||
// Errors associated with a particular package are recorded in the
|
// Errors associated with a particular package are recorded in the
|
||||||
// corresponding Package's Errors list, and do not cause Load to
|
// corresponding Package's Errors list, and do not cause Load to
|
||||||
// return an error. Clients may need to handle such errors before
|
// return an error. Clients may need to handle such errors before
|
||||||
// proceeding with further analysis. The PrintErrors function is
|
// proceeding with further analysis. The [PrintErrors] function is
|
||||||
// provided for convenient display of all errors.
|
// provided for convenient display of all errors.
|
||||||
func Load(cfg *Config, patterns ...string) ([]*Package, error) {
|
func Load(cfg *Config, patterns ...string) ([]*Package, error) {
|
||||||
l := newLoader(cfg)
|
ld := newLoader(cfg)
|
||||||
response, err := defaultDriver(&l.Config, patterns...)
|
response, external, err := defaultDriver(&ld.Config, patterns...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
l.sizes = types.SizesFor(response.Compiler, response.Arch)
|
|
||||||
return l.refine(response)
|
ld.sizes = types.SizesFor(response.Compiler, response.Arch)
|
||||||
|
if ld.sizes == nil && ld.Config.Mode&(NeedTypes|NeedTypesSizes|NeedTypesInfo) != 0 {
|
||||||
|
// Type size information is needed but unavailable.
|
||||||
|
if external {
|
||||||
|
// An external driver may fail to populate the Compiler/GOARCH fields,
|
||||||
|
// especially since they are relatively new (see #63700).
|
||||||
|
// Provide a sensible fallback in this case.
|
||||||
|
ld.sizes = types.SizesFor("gc", runtime.GOARCH)
|
||||||
|
if ld.sizes == nil { // gccgo-only arch
|
||||||
|
ld.sizes = types.SizesFor("gc", "amd64")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Go list should never fail to deliver accurate size information.
|
||||||
|
// Reject the whole Load since the error is the same for every package.
|
||||||
|
return nil, fmt.Errorf("can't determine type sizes for compiler %q on GOARCH %q",
|
||||||
|
response.Compiler, response.Arch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ld.refine(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultDriver is a driver that implements go/packages' fallback behavior.
|
// defaultDriver is a driver that implements go/packages' fallback behavior.
|
||||||
// It will try to request to an external driver, if one exists. If there's
|
// It will try to request to an external driver, if one exists. If there's
|
||||||
// no external driver, or the driver returns a response with NotHandled set,
|
// no external driver, or the driver returns a response with NotHandled set,
|
||||||
// defaultDriver will fall back to the go list driver.
|
// defaultDriver will fall back to the go list driver.
|
||||||
func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
|
// The boolean result indicates that an external driver handled the request.
|
||||||
driver := findExternalDriver(cfg)
|
func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, error) {
|
||||||
if driver == nil {
|
const (
|
||||||
driver = goListDriver
|
// windowsArgMax specifies the maximum command line length for
|
||||||
}
|
// the Windows' CreateProcess function.
|
||||||
response, err := driver(cfg, patterns...)
|
windowsArgMax = 32767
|
||||||
|
// maxEnvSize is a very rough estimation of the maximum environment
|
||||||
|
// size of a user.
|
||||||
|
maxEnvSize = 16384
|
||||||
|
// safeArgMax specifies the maximum safe command line length to use
|
||||||
|
// by the underlying driver excl. the environment. We choose the Windows'
|
||||||
|
// ARG_MAX as the starting point because it's one of the lowest ARG_MAX
|
||||||
|
// constants out of the different supported platforms,
|
||||||
|
// e.g., https://www.in-ulm.de/~mascheck/various/argmax/#results.
|
||||||
|
safeArgMax = windowsArgMax - maxEnvSize
|
||||||
|
)
|
||||||
|
chunks, err := splitIntoChunks(patterns, safeArgMax)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response, err
|
return nil, false, err
|
||||||
} else if response.NotHandled {
|
|
||||||
return goListDriver(cfg, patterns...)
|
|
||||||
}
|
}
|
||||||
return response, nil
|
|
||||||
|
if driver := findExternalDriver(cfg); driver != nil {
|
||||||
|
response, err := callDriverOnChunks(driver, cfg, chunks)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
} else if !response.NotHandled {
|
||||||
|
return response, true, nil
|
||||||
|
}
|
||||||
|
// (fall through)
|
||||||
|
}
|
||||||
|
|
||||||
|
// go list fallback
|
||||||
|
//
|
||||||
|
// Write overlays once, as there are many calls
|
||||||
|
// to 'go list' (one per chunk plus others too).
|
||||||
|
overlay, cleanupOverlay, err := gocommand.WriteOverlays(cfg.Overlay)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
defer cleanupOverlay()
|
||||||
|
cfg.goListOverlayFile = overlay
|
||||||
|
|
||||||
|
response, err := callDriverOnChunks(goListDriver, cfg, chunks)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
return response, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// splitIntoChunks chunks the slice so that the total number of characters
|
||||||
|
// in a chunk is no longer than argMax.
|
||||||
|
func splitIntoChunks(patterns []string, argMax int) ([][]string, error) {
|
||||||
|
if argMax <= 0 {
|
||||||
|
return nil, errors.New("failed to split patterns into chunks, negative safe argMax value")
|
||||||
|
}
|
||||||
|
var chunks [][]string
|
||||||
|
charsInChunk := 0
|
||||||
|
nextChunkStart := 0
|
||||||
|
for i, v := range patterns {
|
||||||
|
vChars := len(v)
|
||||||
|
if vChars > argMax {
|
||||||
|
// a single pattern is longer than the maximum safe ARG_MAX, hardly should happen
|
||||||
|
return nil, errors.New("failed to split patterns into chunks, a pattern is too long")
|
||||||
|
}
|
||||||
|
charsInChunk += vChars + 1 // +1 is for a whitespace between patterns that has to be counted too
|
||||||
|
if charsInChunk > argMax {
|
||||||
|
chunks = append(chunks, patterns[nextChunkStart:i])
|
||||||
|
nextChunkStart = i
|
||||||
|
charsInChunk = vChars
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add the last chunk
|
||||||
|
if nextChunkStart < len(patterns) {
|
||||||
|
chunks = append(chunks, patterns[nextChunkStart:])
|
||||||
|
}
|
||||||
|
return chunks, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func callDriverOnChunks(driver driver, cfg *Config, chunks [][]string) (*DriverResponse, error) {
|
||||||
|
if len(chunks) == 0 {
|
||||||
|
return driver(cfg)
|
||||||
|
}
|
||||||
|
responses := make([]*DriverResponse, len(chunks))
|
||||||
|
errNotHandled := errors.New("driver returned NotHandled")
|
||||||
|
var g errgroup.Group
|
||||||
|
for i, chunk := range chunks {
|
||||||
|
i := i
|
||||||
|
chunk := chunk
|
||||||
|
g.Go(func() (err error) {
|
||||||
|
responses[i], err = driver(cfg, chunk...)
|
||||||
|
if responses[i] != nil && responses[i].NotHandled {
|
||||||
|
err = errNotHandled
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if err := g.Wait(); err != nil {
|
||||||
|
if errors.Is(err, errNotHandled) {
|
||||||
|
return &DriverResponse{NotHandled: true}, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return mergeResponses(responses...), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeResponses(responses ...*DriverResponse) *DriverResponse {
|
||||||
|
if len(responses) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
response := newDeduper()
|
||||||
|
response.dr.NotHandled = false
|
||||||
|
response.dr.Compiler = responses[0].Compiler
|
||||||
|
response.dr.Arch = responses[0].Arch
|
||||||
|
response.dr.GoVersion = responses[0].GoVersion
|
||||||
|
for _, v := range responses {
|
||||||
|
response.addAll(v)
|
||||||
|
}
|
||||||
|
return response.dr
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Package describes a loaded Go package.
|
// A Package describes a loaded Go package.
|
||||||
|
//
|
||||||
|
// It also defines part of the JSON schema of [DriverResponse].
|
||||||
|
// See the package documentation for an overview.
|
||||||
type Package struct {
|
type Package struct {
|
||||||
// ID is a unique identifier for a package,
|
// ID is a unique identifier for a package,
|
||||||
// in a syntax provided by the underlying build system.
|
// in a syntax provided by the underlying build system.
|
||||||
@ -344,19 +488,30 @@ type Package struct {
|
|||||||
// to corresponding loaded Packages.
|
// to corresponding loaded Packages.
|
||||||
Imports map[string]*Package
|
Imports map[string]*Package
|
||||||
|
|
||||||
|
// Module is the module information for the package if it exists.
|
||||||
|
//
|
||||||
|
// Note: it may be missing for std and cmd; see Go issue #65816.
|
||||||
|
Module *Module
|
||||||
|
|
||||||
|
// -- The following fields are not part of the driver JSON schema. --
|
||||||
|
|
||||||
// Types provides type information for the package.
|
// Types provides type information for the package.
|
||||||
// The NeedTypes LoadMode bit sets this field for packages matching the
|
// The NeedTypes LoadMode bit sets this field for packages matching the
|
||||||
// patterns; type information for dependencies may be missing or incomplete,
|
// patterns; type information for dependencies may be missing or incomplete,
|
||||||
// unless NeedDeps and NeedImports are also set.
|
// unless NeedDeps and NeedImports are also set.
|
||||||
Types *types.Package
|
//
|
||||||
|
// Each call to [Load] returns a consistent set of type
|
||||||
|
// symbols, as defined by the comment at [types.Identical].
|
||||||
|
// Avoid mixing type information from two or more calls to [Load].
|
||||||
|
Types *types.Package `json:"-"`
|
||||||
|
|
||||||
// Fset provides position information for Types, TypesInfo, and Syntax.
|
// Fset provides position information for Types, TypesInfo, and Syntax.
|
||||||
// It is set only when Types is set.
|
// It is set only when Types is set.
|
||||||
Fset *token.FileSet
|
Fset *token.FileSet `json:"-"`
|
||||||
|
|
||||||
// IllTyped indicates whether the package or any dependency contains errors.
|
// IllTyped indicates whether the package or any dependency contains errors.
|
||||||
// It is set only when Types is set.
|
// It is set only when Types is set.
|
||||||
IllTyped bool
|
IllTyped bool `json:"-"`
|
||||||
|
|
||||||
// Syntax is the package's syntax trees, for the files listed in CompiledGoFiles.
|
// Syntax is the package's syntax trees, for the files listed in CompiledGoFiles.
|
||||||
//
|
//
|
||||||
@ -366,26 +521,28 @@ type Package struct {
|
|||||||
//
|
//
|
||||||
// Syntax is kept in the same order as CompiledGoFiles, with the caveat that nils are
|
// Syntax is kept in the same order as CompiledGoFiles, with the caveat that nils are
|
||||||
// removed. If parsing returned nil, Syntax may be shorter than CompiledGoFiles.
|
// removed. If parsing returned nil, Syntax may be shorter than CompiledGoFiles.
|
||||||
Syntax []*ast.File
|
Syntax []*ast.File `json:"-"`
|
||||||
|
|
||||||
// TypesInfo provides type information about the package's syntax trees.
|
// TypesInfo provides type information about the package's syntax trees.
|
||||||
// It is set only when Syntax is set.
|
// It is set only when Syntax is set.
|
||||||
TypesInfo *types.Info
|
TypesInfo *types.Info `json:"-"`
|
||||||
|
|
||||||
// TypesSizes provides the effective size function for types in TypesInfo.
|
// TypesSizes provides the effective size function for types in TypesInfo.
|
||||||
TypesSizes types.Sizes
|
TypesSizes types.Sizes `json:"-"`
|
||||||
|
|
||||||
|
// -- internal --
|
||||||
|
|
||||||
// forTest is the package under test, if any.
|
// forTest is the package under test, if any.
|
||||||
forTest string
|
forTest string
|
||||||
|
|
||||||
// depsErrors is the DepsErrors field from the go list response, if any.
|
// depsErrors is the DepsErrors field from the go list response, if any.
|
||||||
depsErrors []*packagesinternal.PackageError
|
depsErrors []*packagesinternal.PackageError
|
||||||
|
|
||||||
// module is the module information for the package if it exists.
|
|
||||||
Module *Module
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module provides module information for a package.
|
// Module provides module information for a package.
|
||||||
|
//
|
||||||
|
// It also defines part of the JSON schema of [DriverResponse].
|
||||||
|
// See the package documentation for an overview.
|
||||||
type Module struct {
|
type Module struct {
|
||||||
Path string // module path
|
Path string // module path
|
||||||
Version string // module version
|
Version string // module version
|
||||||
@ -411,12 +568,6 @@ func init() {
|
|||||||
packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError {
|
packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError {
|
||||||
return p.(*Package).depsErrors
|
return p.(*Package).depsErrors
|
||||||
}
|
}
|
||||||
packagesinternal.GetGoCmdRunner = func(config interface{}) *gocommand.Runner {
|
|
||||||
return config.(*Config).gocmdRunner
|
|
||||||
}
|
|
||||||
packagesinternal.SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) {
|
|
||||||
config.(*Config).gocmdRunner = runner
|
|
||||||
}
|
|
||||||
packagesinternal.SetModFile = func(config interface{}, value string) {
|
packagesinternal.SetModFile = func(config interface{}, value string) {
|
||||||
config.(*Config).modFile = value
|
config.(*Config).modFile = value
|
||||||
}
|
}
|
||||||
@ -524,6 +675,7 @@ func (p *Package) UnmarshalJSON(b []byte) error {
|
|||||||
OtherFiles: flat.OtherFiles,
|
OtherFiles: flat.OtherFiles,
|
||||||
EmbedFiles: flat.EmbedFiles,
|
EmbedFiles: flat.EmbedFiles,
|
||||||
EmbedPatterns: flat.EmbedPatterns,
|
EmbedPatterns: flat.EmbedPatterns,
|
||||||
|
IgnoredFiles: flat.IgnoredFiles,
|
||||||
ExportFile: flat.ExportFile,
|
ExportFile: flat.ExportFile,
|
||||||
}
|
}
|
||||||
if len(flat.Imports) > 0 {
|
if len(flat.Imports) > 0 {
|
||||||
@ -553,7 +705,7 @@ type loaderPackage struct {
|
|||||||
type loader struct {
|
type loader struct {
|
||||||
pkgs map[string]*loaderPackage
|
pkgs map[string]*loaderPackage
|
||||||
Config
|
Config
|
||||||
sizes types.Sizes
|
sizes types.Sizes // non-nil if needed by mode
|
||||||
parseCache map[string]*parseValue
|
parseCache map[string]*parseValue
|
||||||
parseCacheMu sync.Mutex
|
parseCacheMu sync.Mutex
|
||||||
exportMu sync.Mutex // enforces mutual exclusion of exportdata operations
|
exportMu sync.Mutex // enforces mutual exclusion of exportdata operations
|
||||||
@ -622,6 +774,7 @@ func newLoader(cfg *Config) *loader {
|
|||||||
// because we load source if export data is missing.
|
// because we load source if export data is missing.
|
||||||
if ld.ParseFile == nil {
|
if ld.ParseFile == nil {
|
||||||
ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
|
ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
|
||||||
|
// We implicitly promise to keep doing ast.Object resolution. :(
|
||||||
const mode = parser.AllErrors | parser.ParseComments
|
const mode = parser.AllErrors | parser.ParseComments
|
||||||
return parser.ParseFile(fset, filename, src, mode)
|
return parser.ParseFile(fset, filename, src, mode)
|
||||||
}
|
}
|
||||||
@ -633,7 +786,7 @@ func newLoader(cfg *Config) *loader {
|
|||||||
|
|
||||||
// refine connects the supplied packages into a graph and then adds type
|
// refine connects the supplied packages into a graph and then adds type
|
||||||
// and syntax information as requested by the LoadMode.
|
// and syntax information as requested by the LoadMode.
|
||||||
func (ld *loader) refine(response *driverResponse) ([]*Package, error) {
|
func (ld *loader) refine(response *DriverResponse) ([]*Package, error) {
|
||||||
roots := response.Roots
|
roots := response.Roots
|
||||||
rootMap := make(map[string]int, len(roots))
|
rootMap := make(map[string]int, len(roots))
|
||||||
for i, root := range roots {
|
for i, root := range roots {
|
||||||
@ -678,39 +831,38 @@ func (ld *loader) refine(response *driverResponse) ([]*Package, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Materialize the import graph.
|
if ld.Mode&NeedImports != 0 {
|
||||||
|
// Materialize the import graph.
|
||||||
|
|
||||||
const (
|
const (
|
||||||
white = 0 // new
|
white = 0 // new
|
||||||
grey = 1 // in progress
|
grey = 1 // in progress
|
||||||
black = 2 // complete
|
black = 2 // complete
|
||||||
)
|
)
|
||||||
|
|
||||||
// visit traverses the import graph, depth-first,
|
// visit traverses the import graph, depth-first,
|
||||||
// and materializes the graph as Packages.Imports.
|
// and materializes the graph as Packages.Imports.
|
||||||
//
|
//
|
||||||
// Valid imports are saved in the Packages.Import map.
|
// Valid imports are saved in the Packages.Import map.
|
||||||
// Invalid imports (cycles and missing nodes) are saved in the importErrors map.
|
// Invalid imports (cycles and missing nodes) are saved in the importErrors map.
|
||||||
// Thus, even in the presence of both kinds of errors, the Import graph remains a DAG.
|
// Thus, even in the presence of both kinds of errors,
|
||||||
//
|
// the Import graph remains a DAG.
|
||||||
// visit returns whether the package needs src or has a transitive
|
//
|
||||||
// dependency on a package that does. These are the only packages
|
// visit returns whether the package needs src or has a transitive
|
||||||
// for which we load source code.
|
// dependency on a package that does. These are the only packages
|
||||||
var stack []*loaderPackage
|
// for which we load source code.
|
||||||
var visit func(lpkg *loaderPackage) bool
|
var stack []*loaderPackage
|
||||||
var srcPkgs []*loaderPackage
|
var visit func(lpkg *loaderPackage) bool
|
||||||
visit = func(lpkg *loaderPackage) bool {
|
visit = func(lpkg *loaderPackage) bool {
|
||||||
switch lpkg.color {
|
switch lpkg.color {
|
||||||
case black:
|
case black:
|
||||||
return lpkg.needsrc
|
return lpkg.needsrc
|
||||||
case grey:
|
case grey:
|
||||||
panic("internal error: grey node")
|
panic("internal error: grey node")
|
||||||
}
|
}
|
||||||
lpkg.color = grey
|
lpkg.color = grey
|
||||||
stack = append(stack, lpkg) // push
|
stack = append(stack, lpkg) // push
|
||||||
stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports
|
stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports
|
||||||
// If NeedImports isn't set, the imports fields will all be zeroed out.
|
|
||||||
if ld.Mode&NeedImports != 0 {
|
|
||||||
lpkg.Imports = make(map[string]*Package, len(stubs))
|
lpkg.Imports = make(map[string]*Package, len(stubs))
|
||||||
for importPath, ipkg := range stubs {
|
for importPath, ipkg := range stubs {
|
||||||
var importErr error
|
var importErr error
|
||||||
@ -734,40 +886,39 @@ func (ld *loader) refine(response *driverResponse) ([]*Package, error) {
|
|||||||
}
|
}
|
||||||
lpkg.Imports[importPath] = imp.Package
|
lpkg.Imports[importPath] = imp.Package
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if lpkg.needsrc {
|
|
||||||
srcPkgs = append(srcPkgs, lpkg)
|
|
||||||
}
|
|
||||||
if ld.Mode&NeedTypesSizes != 0 {
|
|
||||||
lpkg.TypesSizes = ld.sizes
|
|
||||||
}
|
|
||||||
stack = stack[:len(stack)-1] // pop
|
|
||||||
lpkg.color = black
|
|
||||||
|
|
||||||
return lpkg.needsrc
|
// Complete type information is required for the
|
||||||
}
|
// immediate dependencies of each source package.
|
||||||
|
if lpkg.needsrc && ld.Mode&NeedTypes != 0 {
|
||||||
|
for _, ipkg := range lpkg.Imports {
|
||||||
|
ld.pkgs[ipkg.ID].needtypes = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ld.Mode&NeedImports == 0 {
|
// NeedTypeSizes causes TypeSizes to be set even
|
||||||
// We do this to drop the stub import packages that we are not even going to try to resolve.
|
// on packages for which types aren't needed.
|
||||||
for _, lpkg := range initial {
|
if ld.Mode&NeedTypesSizes != 0 {
|
||||||
lpkg.Imports = nil
|
lpkg.TypesSizes = ld.sizes
|
||||||
|
}
|
||||||
|
stack = stack[:len(stack)-1] // pop
|
||||||
|
lpkg.color = black
|
||||||
|
|
||||||
|
return lpkg.needsrc
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// For each initial package, create its import DAG.
|
// For each initial package, create its import DAG.
|
||||||
for _, lpkg := range initial {
|
for _, lpkg := range initial {
|
||||||
visit(lpkg)
|
visit(lpkg)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if ld.Mode&NeedImports != 0 && ld.Mode&NeedTypes != 0 {
|
} else {
|
||||||
for _, lpkg := range srcPkgs {
|
// !NeedImports: drop the stub (ID-only) import packages
|
||||||
// Complete type information is required for the
|
// that we are not even going to try to resolve.
|
||||||
// immediate dependencies of each source package.
|
for _, lpkg := range initial {
|
||||||
for _, ipkg := range lpkg.Imports {
|
lpkg.Imports = nil
|
||||||
imp := ld.pkgs[ipkg.ID]
|
|
||||||
imp.needtypes = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load type data and syntax if needed, starting at
|
// Load type data and syntax if needed, starting at
|
||||||
// the initial packages (roots of the import DAG).
|
// the initial packages (roots of the import DAG).
|
||||||
if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 {
|
if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 {
|
||||||
@ -782,6 +933,12 @@ func (ld *loader) refine(response *driverResponse) ([]*Package, error) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the context is done, return its error and
|
||||||
|
// throw out [likely] incomplete packages.
|
||||||
|
if err := ld.Context.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
result := make([]*Package, len(initial))
|
result := make([]*Package, len(initial))
|
||||||
for i, lpkg := range initial {
|
for i, lpkg := range initial {
|
||||||
result[i] = lpkg.Package
|
result[i] = lpkg.Package
|
||||||
@ -815,12 +972,14 @@ func (ld *loader) refine(response *driverResponse) ([]*Package, error) {
|
|||||||
}
|
}
|
||||||
if ld.requestedMode&NeedTypes == 0 {
|
if ld.requestedMode&NeedTypes == 0 {
|
||||||
ld.pkgs[i].Types = nil
|
ld.pkgs[i].Types = nil
|
||||||
ld.pkgs[i].Fset = nil
|
|
||||||
ld.pkgs[i].IllTyped = false
|
ld.pkgs[i].IllTyped = false
|
||||||
}
|
}
|
||||||
if ld.requestedMode&NeedSyntax == 0 {
|
if ld.requestedMode&NeedSyntax == 0 {
|
||||||
ld.pkgs[i].Syntax = nil
|
ld.pkgs[i].Syntax = nil
|
||||||
}
|
}
|
||||||
|
if ld.requestedMode&NeedTypes == 0 && ld.requestedMode&NeedSyntax == 0 {
|
||||||
|
ld.pkgs[i].Fset = nil
|
||||||
|
}
|
||||||
if ld.requestedMode&NeedTypesInfo == 0 {
|
if ld.requestedMode&NeedTypesInfo == 0 {
|
||||||
ld.pkgs[i].TypesInfo = nil
|
ld.pkgs[i].TypesInfo = nil
|
||||||
}
|
}
|
||||||
@ -877,6 +1036,14 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
|
|||||||
lpkg.Types = types.NewPackage(lpkg.PkgPath, lpkg.Name)
|
lpkg.Types = types.NewPackage(lpkg.PkgPath, lpkg.Name)
|
||||||
lpkg.Fset = ld.Fset
|
lpkg.Fset = ld.Fset
|
||||||
|
|
||||||
|
// Start shutting down if the context is done and do not load
|
||||||
|
// source or export data files.
|
||||||
|
// Packages that import this one will have ld.Context.Err() != nil.
|
||||||
|
// ld.Context.Err() will be returned later by refine.
|
||||||
|
if ld.Context.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Subtle: we populate all Types fields with an empty Package
|
// Subtle: we populate all Types fields with an empty Package
|
||||||
// before loading export data so that export data processing
|
// before loading export data so that export data processing
|
||||||
// never has to create a types.Package for an indirect dependency,
|
// never has to create a types.Package for an indirect dependency,
|
||||||
@ -996,15 +1163,23 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start shutting down if the context is done and do not type check.
|
||||||
|
// Packages that import this one will have ld.Context.Err() != nil.
|
||||||
|
// ld.Context.Err() will be returned later by refine.
|
||||||
|
if ld.Context.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
lpkg.TypesInfo = &types.Info{
|
lpkg.TypesInfo = &types.Info{
|
||||||
Types: make(map[ast.Expr]types.TypeAndValue),
|
Types: make(map[ast.Expr]types.TypeAndValue),
|
||||||
Defs: make(map[*ast.Ident]types.Object),
|
Defs: make(map[*ast.Ident]types.Object),
|
||||||
Uses: make(map[*ast.Ident]types.Object),
|
Uses: make(map[*ast.Ident]types.Object),
|
||||||
Implicits: make(map[ast.Node]types.Object),
|
Implicits: make(map[ast.Node]types.Object),
|
||||||
|
Instances: make(map[*ast.Ident]types.Instance),
|
||||||
Scopes: make(map[ast.Node]*types.Scope),
|
Scopes: make(map[ast.Node]*types.Scope),
|
||||||
Selections: make(map[*ast.SelectorExpr]*types.Selection),
|
Selections: make(map[*ast.SelectorExpr]*types.Selection),
|
||||||
}
|
}
|
||||||
typeparams.InitInstanceInfo(lpkg.TypesInfo)
|
versions.InitFileVersions(lpkg.TypesInfo)
|
||||||
lpkg.TypesSizes = ld.sizes
|
lpkg.TypesSizes = ld.sizes
|
||||||
|
|
||||||
importer := importerFunc(func(path string) (*types.Package, error) {
|
importer := importerFunc(func(path string) (*types.Package, error) {
|
||||||
@ -1042,10 +1217,10 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
|
|||||||
IgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial,
|
IgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial,
|
||||||
|
|
||||||
Error: appendError,
|
Error: appendError,
|
||||||
Sizes: ld.sizes,
|
Sizes: ld.sizes, // may be nil
|
||||||
}
|
}
|
||||||
if lpkg.Module != nil && lpkg.Module.GoVersion != "" {
|
if lpkg.Module != nil && lpkg.Module.GoVersion != "" {
|
||||||
typesinternal.SetGoVersion(tc, "go"+lpkg.Module.GoVersion)
|
tc.GoVersion = "go" + lpkg.Module.GoVersion
|
||||||
}
|
}
|
||||||
if (ld.Mode & typecheckCgo) != 0 {
|
if (ld.Mode & typecheckCgo) != 0 {
|
||||||
if !typesinternal.SetUsesCgo(tc) {
|
if !typesinternal.SetUsesCgo(tc) {
|
||||||
@ -1056,10 +1231,24 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax)
|
|
||||||
|
|
||||||
|
typErr := types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax)
|
||||||
lpkg.importErrors = nil // no longer needed
|
lpkg.importErrors = nil // no longer needed
|
||||||
|
|
||||||
|
// In go/types go1.21 and go1.22, Checker.Files failed fast with a
|
||||||
|
// a "too new" error, without calling tc.Error and without
|
||||||
|
// proceeding to type-check the package (#66525).
|
||||||
|
// We rely on the runtimeVersion error to give the suggested remedy.
|
||||||
|
if typErr != nil && len(lpkg.Errors) == 0 && len(lpkg.Syntax) > 0 {
|
||||||
|
if msg := typErr.Error(); strings.HasPrefix(msg, "package requires newer Go version") {
|
||||||
|
appendError(types.Error{
|
||||||
|
Fset: ld.Fset,
|
||||||
|
Pos: lpkg.Syntax[0].Package,
|
||||||
|
Msg: msg,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If !Cgo, the type-checker uses FakeImportC mode, so
|
// If !Cgo, the type-checker uses FakeImportC mode, so
|
||||||
// it doesn't invoke the importer for import "C",
|
// it doesn't invoke the importer for import "C",
|
||||||
// nor report an error for the import,
|
// nor report an error for the import,
|
||||||
@ -1081,6 +1270,12 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If types.Checker.Files had an error that was unreported,
|
||||||
|
// make sure to report the unknown error so the package is illTyped.
|
||||||
|
if typErr != nil && len(lpkg.Errors) == 0 {
|
||||||
|
appendError(typErr)
|
||||||
|
}
|
||||||
|
|
||||||
// Record accumulated errors.
|
// Record accumulated errors.
|
||||||
illTyped := len(lpkg.Errors) > 0
|
illTyped := len(lpkg.Errors) > 0
|
||||||
if !illTyped {
|
if !illTyped {
|
||||||
@ -1152,11 +1347,6 @@ func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) {
|
|||||||
parsed := make([]*ast.File, n)
|
parsed := make([]*ast.File, n)
|
||||||
errors := make([]error, n)
|
errors := make([]error, n)
|
||||||
for i, file := range filenames {
|
for i, file := range filenames {
|
||||||
if ld.Config.Context.Err() != nil {
|
|
||||||
parsed[i] = nil
|
|
||||||
errors[i] = ld.Config.Context.Err()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(i int, filename string) {
|
go func(i int, filename string) {
|
||||||
parsed[i], errors[i] = ld.parseFile(filename)
|
parsed[i], errors[i] = ld.parseFile(filename)
|
||||||
@ -1322,6 +1512,10 @@ func impliedLoadMode(loadMode LoadMode) LoadMode {
|
|||||||
// All these things require knowing the import graph.
|
// All these things require knowing the import graph.
|
||||||
loadMode |= NeedImports
|
loadMode |= NeedImports
|
||||||
}
|
}
|
||||||
|
if loadMode&NeedTypes != 0 {
|
||||||
|
// Types require the GoVersion from Module.
|
||||||
|
loadMode |= NeedModule
|
||||||
|
}
|
||||||
|
|
||||||
return loadMode
|
return loadMode
|
||||||
}
|
}
|
||||||
|
9
vendor/golang.org/x/tools/go/packages/visit.go
generated
vendored
9
vendor/golang.org/x/tools/go/packages/visit.go
generated
vendored
@ -49,11 +49,20 @@ func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) {
|
|||||||
// PrintErrors returns the number of errors printed.
|
// PrintErrors returns the number of errors printed.
|
||||||
func PrintErrors(pkgs []*Package) int {
|
func PrintErrors(pkgs []*Package) int {
|
||||||
var n int
|
var n int
|
||||||
|
errModules := make(map[*Module]bool)
|
||||||
Visit(pkgs, nil, func(pkg *Package) {
|
Visit(pkgs, nil, func(pkg *Package) {
|
||||||
for _, err := range pkg.Errors {
|
for _, err := range pkg.Errors {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print pkg.Module.Error once if present.
|
||||||
|
mod := pkg.Module
|
||||||
|
if mod != nil && mod.Error != nil && !errModules[mod] {
|
||||||
|
errModules[mod] = true
|
||||||
|
fmt.Fprintln(os.Stderr, mod.Error.Err)
|
||||||
|
n++
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
237
vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
generated
vendored
237
vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
generated
vendored
@ -26,15 +26,15 @@ package objectpath
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/types"
|
"go/types"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
_ "unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/tools/internal/typeparams"
|
"golang.org/x/tools/internal/aliases"
|
||||||
"golang.org/x/tools/internal/typesinternal"
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO(adonovan): think about generic aliases.
|
||||||
|
|
||||||
// A Path is an opaque name that identifies a types.Object
|
// A Path is an opaque name that identifies a types.Object
|
||||||
// relative to its package. Conceptually, the name consists of a
|
// relative to its package. Conceptually, the name consists of a
|
||||||
// sequence of destructuring operations applied to the package scope
|
// sequence of destructuring operations applied to the package scope
|
||||||
@ -51,7 +51,7 @@ type Path string
|
|||||||
//
|
//
|
||||||
// PO package->object Package.Scope.Lookup
|
// PO package->object Package.Scope.Lookup
|
||||||
// OT object->type Object.Type
|
// OT object->type Object.Type
|
||||||
// TT type->type Type.{Elem,Key,Params,Results,Underlying} [EKPRU]
|
// TT type->type Type.{Elem,Key,{,{,Recv}Type}Params,Results,Underlying,Rhs} [EKPRUTrCa]
|
||||||
// TO type->object Type.{At,Field,Method,Obj} [AFMO]
|
// TO type->object Type.{At,Field,Method,Obj} [AFMO]
|
||||||
//
|
//
|
||||||
// All valid paths start with a package and end at an object
|
// All valid paths start with a package and end at an object
|
||||||
@ -63,8 +63,8 @@ type Path string
|
|||||||
// - The only PO operator is Package.Scope.Lookup, which requires an identifier.
|
// - The only PO operator is Package.Scope.Lookup, which requires an identifier.
|
||||||
// - The only OT operator is Object.Type,
|
// - The only OT operator is Object.Type,
|
||||||
// which we encode as '.' because dot cannot appear in an identifier.
|
// which we encode as '.' because dot cannot appear in an identifier.
|
||||||
// - The TT operators are encoded as [EKPRUTC];
|
// - The TT operators are encoded as [EKPRUTrCa];
|
||||||
// one of these (TypeParam) requires an integer operand,
|
// two of these ({,Recv}TypeParams) require an integer operand,
|
||||||
// which is encoded as a string of decimal digits.
|
// which is encoded as a string of decimal digits.
|
||||||
// - The TO operators are encoded as [AFMO];
|
// - The TO operators are encoded as [AFMO];
|
||||||
// three of these (At,Field,Method) require an integer operand,
|
// three of these (At,Field,Method) require an integer operand,
|
||||||
@ -98,19 +98,21 @@ const (
|
|||||||
opType = '.' // .Type() (Object)
|
opType = '.' // .Type() (Object)
|
||||||
|
|
||||||
// type->type operators
|
// type->type operators
|
||||||
opElem = 'E' // .Elem() (Pointer, Slice, Array, Chan, Map)
|
opElem = 'E' // .Elem() (Pointer, Slice, Array, Chan, Map)
|
||||||
opKey = 'K' // .Key() (Map)
|
opKey = 'K' // .Key() (Map)
|
||||||
opParams = 'P' // .Params() (Signature)
|
opParams = 'P' // .Params() (Signature)
|
||||||
opResults = 'R' // .Results() (Signature)
|
opResults = 'R' // .Results() (Signature)
|
||||||
opUnderlying = 'U' // .Underlying() (Named)
|
opUnderlying = 'U' // .Underlying() (Named)
|
||||||
opTypeParam = 'T' // .TypeParams.At(i) (Named, Signature)
|
opTypeParam = 'T' // .TypeParams.At(i) (Named, Signature)
|
||||||
opConstraint = 'C' // .Constraint() (TypeParam)
|
opRecvTypeParam = 'r' // .RecvTypeParams.At(i) (Signature)
|
||||||
|
opConstraint = 'C' // .Constraint() (TypeParam)
|
||||||
|
opRhs = 'a' // .Rhs() (Alias)
|
||||||
|
|
||||||
// type->object operators
|
// type->object operators
|
||||||
opAt = 'A' // .At(i) (Tuple)
|
opAt = 'A' // .At(i) (Tuple)
|
||||||
opField = 'F' // .Field(i) (Struct)
|
opField = 'F' // .Field(i) (Struct)
|
||||||
opMethod = 'M' // .Method(i) (Named or Interface; not Struct: "promoted" names are ignored)
|
opMethod = 'M' // .Method(i) (Named or Interface; not Struct: "promoted" names are ignored)
|
||||||
opObj = 'O' // .Obj() (Named, TypeParam)
|
opObj = 'O' // .Obj() (Named, TypeParam)
|
||||||
)
|
)
|
||||||
|
|
||||||
// For is equivalent to new(Encoder).For(obj).
|
// For is equivalent to new(Encoder).For(obj).
|
||||||
@ -123,20 +125,7 @@ func For(obj types.Object) (Path, error) {
|
|||||||
// An Encoder amortizes the cost of encoding the paths of multiple objects.
|
// An Encoder amortizes the cost of encoding the paths of multiple objects.
|
||||||
// The zero value of an Encoder is ready to use.
|
// The zero value of an Encoder is ready to use.
|
||||||
type Encoder struct {
|
type Encoder struct {
|
||||||
scopeMemo map[*types.Scope][]types.Object // memoization of scopeObjects
|
scopeMemo map[*types.Scope][]types.Object // memoization of scopeObjects
|
||||||
namedMethodsMemo map[*types.Named][]*types.Func // memoization of namedMethods()
|
|
||||||
skipMethodSorting bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expose back doors so that gopls can avoid method sorting, which can dominate
|
|
||||||
// analysis on certain repositories.
|
|
||||||
//
|
|
||||||
// TODO(golang/go#61443): remove this.
|
|
||||||
func init() {
|
|
||||||
typesinternal.SkipEncoderMethodSorting = func(enc interface{}) {
|
|
||||||
enc.(*Encoder).skipMethodSorting = true
|
|
||||||
}
|
|
||||||
typesinternal.ObjectpathObject = object
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For returns the path to an object relative to its package,
|
// For returns the path to an object relative to its package,
|
||||||
@ -239,7 +228,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
|
|||||||
// Reject obviously non-viable cases.
|
// Reject obviously non-viable cases.
|
||||||
switch obj := obj.(type) {
|
switch obj := obj.(type) {
|
||||||
case *types.TypeName:
|
case *types.TypeName:
|
||||||
if _, ok := obj.Type().(*typeparams.TypeParam); !ok {
|
if _, ok := types.Unalias(obj.Type()).(*types.TypeParam); !ok {
|
||||||
// With the exception of type parameters, only package-level type names
|
// With the exception of type parameters, only package-level type names
|
||||||
// have a path.
|
// have a path.
|
||||||
return "", fmt.Errorf("no path for %v", obj)
|
return "", fmt.Errorf("no path for %v", obj)
|
||||||
@ -291,21 +280,26 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
|
|||||||
path = append(path, opType)
|
path = append(path, opType)
|
||||||
|
|
||||||
T := o.Type()
|
T := o.Type()
|
||||||
|
if alias, ok := T.(*types.Alias); ok {
|
||||||
|
if r := findTypeParam(obj, aliases.TypeParams(alias), path, opTypeParam, nil); r != nil {
|
||||||
|
return Path(r), nil
|
||||||
|
}
|
||||||
|
if r := find(obj, aliases.Rhs(alias), append(path, opRhs), nil); r != nil {
|
||||||
|
return Path(r), nil
|
||||||
|
}
|
||||||
|
|
||||||
if tname.IsAlias() {
|
} else if tname.IsAlias() {
|
||||||
// type alias
|
// legacy alias
|
||||||
if r := find(obj, T, path, nil); r != nil {
|
if r := find(obj, T, path, nil); r != nil {
|
||||||
return Path(r), nil
|
return Path(r), nil
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if named, _ := T.(*types.Named); named != nil {
|
} else if named, ok := T.(*types.Named); ok {
|
||||||
if r := findTypeParam(obj, typeparams.ForNamed(named), path, nil); r != nil {
|
|
||||||
// generic named type
|
|
||||||
return Path(r), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// defined (named) type
|
// defined (named) type
|
||||||
if r := find(obj, T.Underlying(), append(path, opUnderlying), nil); r != nil {
|
if r := findTypeParam(obj, named.TypeParams(), path, opTypeParam, nil); r != nil {
|
||||||
|
return Path(r), nil
|
||||||
|
}
|
||||||
|
if r := find(obj, named.Underlying(), append(path, opUnderlying), nil); r != nil {
|
||||||
return Path(r), nil
|
return Path(r), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,33 +320,20 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Inspect declared methods of defined types.
|
// Inspect declared methods of defined types.
|
||||||
if T, ok := o.Type().(*types.Named); ok {
|
if T, ok := types.Unalias(o.Type()).(*types.Named); ok {
|
||||||
path = append(path, opType)
|
path = append(path, opType)
|
||||||
if !enc.skipMethodSorting {
|
// The method index here is always with respect
|
||||||
// Note that method index here is always with respect
|
// to the underlying go/types data structures,
|
||||||
// to canonical ordering of methods, regardless of how
|
// which ultimately derives from source order
|
||||||
// they appear in the underlying type.
|
// and must be preserved by export data.
|
||||||
for i, m := range enc.namedMethods(T) {
|
for i := 0; i < T.NumMethods(); i++ {
|
||||||
path2 := appendOpArg(path, opMethod, i)
|
m := T.Method(i)
|
||||||
if m == obj {
|
path2 := appendOpArg(path, opMethod, i)
|
||||||
return Path(path2), nil // found declared method
|
if m == obj {
|
||||||
}
|
return Path(path2), nil // found declared method
|
||||||
if r := find(obj, m.Type(), append(path2, opType), nil); r != nil {
|
|
||||||
return Path(r), nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
if r := find(obj, m.Type(), append(path2, opType), nil); r != nil {
|
||||||
// This branch must match the logic in the branch above, using go/types
|
return Path(r), nil
|
||||||
// APIs without sorting.
|
|
||||||
for i := 0; i < T.NumMethods(); i++ {
|
|
||||||
m := T.Method(i)
|
|
||||||
path2 := appendOpArg(path, opMethod, i)
|
|
||||||
if m == obj {
|
|
||||||
return Path(path2), nil // found declared method
|
|
||||||
}
|
|
||||||
if r := find(obj, m.Type(), append(path2, opType), nil); r != nil {
|
|
||||||
return Path(r), nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -420,17 +401,12 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
|
|||||||
// of objectpath will only be giving us origin methods, anyway, as referring
|
// of objectpath will only be giving us origin methods, anyway, as referring
|
||||||
// to instantiated methods is usually not useful.
|
// to instantiated methods is usually not useful.
|
||||||
|
|
||||||
if typeparams.OriginMethod(meth) != meth {
|
if meth.Origin() != meth {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
recvT := meth.Type().(*types.Signature).Recv().Type()
|
_, named := typesinternal.ReceiverNamed(meth.Type().(*types.Signature).Recv())
|
||||||
if ptr, ok := recvT.(*types.Pointer); ok {
|
if named == nil {
|
||||||
recvT = ptr.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
named, ok := recvT.(*types.Named)
|
|
||||||
if !ok {
|
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,22 +424,13 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
|
|||||||
path = append(path, name...)
|
path = append(path, name...)
|
||||||
path = append(path, opType)
|
path = append(path, opType)
|
||||||
|
|
||||||
if !enc.skipMethodSorting {
|
// Method indices are w.r.t. the go/types data structures,
|
||||||
for i, m := range enc.namedMethods(named) {
|
// ultimately deriving from source order,
|
||||||
if m == meth {
|
// which is preserved by export data.
|
||||||
path = appendOpArg(path, opMethod, i)
|
for i := 0; i < named.NumMethods(); i++ {
|
||||||
return Path(path), true
|
if named.Method(i) == meth {
|
||||||
}
|
path = appendOpArg(path, opMethod, i)
|
||||||
}
|
return Path(path), true
|
||||||
} else {
|
|
||||||
// This branch must match the logic of the branch above, using go/types
|
|
||||||
// APIs without sorting.
|
|
||||||
for i := 0; i < named.NumMethods(); i++ {
|
|
||||||
m := named.Method(i)
|
|
||||||
if m == meth {
|
|
||||||
path = appendOpArg(path, opMethod, i)
|
|
||||||
return Path(path), true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,6 +449,8 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
|
|||||||
// nil, it will be allocated as necessary.
|
// nil, it will be allocated as necessary.
|
||||||
func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte {
|
func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte {
|
||||||
switch T := T.(type) {
|
switch T := T.(type) {
|
||||||
|
case *types.Alias:
|
||||||
|
return find(obj, types.Unalias(T), path, seen)
|
||||||
case *types.Basic, *types.Named:
|
case *types.Basic, *types.Named:
|
||||||
// Named types belonging to pkg were handled already,
|
// Named types belonging to pkg were handled already,
|
||||||
// so T must belong to another package. No path.
|
// so T must belong to another package. No path.
|
||||||
@ -500,7 +469,10 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]
|
|||||||
}
|
}
|
||||||
return find(obj, T.Elem(), append(path, opElem), seen)
|
return find(obj, T.Elem(), append(path, opElem), seen)
|
||||||
case *types.Signature:
|
case *types.Signature:
|
||||||
if r := findTypeParam(obj, typeparams.ForSignature(T), path, seen); r != nil {
|
if r := findTypeParam(obj, T.RecvTypeParams(), path, opRecvTypeParam, nil); r != nil {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
if r := findTypeParam(obj, T.TypeParams(), path, opTypeParam, seen); r != nil {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
if r := find(obj, T.Params(), append(path, opParams), seen); r != nil {
|
if r := find(obj, T.Params(), append(path, opParams), seen); r != nil {
|
||||||
@ -543,7 +515,7 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case *typeparams.TypeParam:
|
case *types.TypeParam:
|
||||||
name := T.Obj()
|
name := T.Obj()
|
||||||
if name == obj {
|
if name == obj {
|
||||||
return append(path, opObj)
|
return append(path, opObj)
|
||||||
@ -563,10 +535,10 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]
|
|||||||
panic(T)
|
panic(T)
|
||||||
}
|
}
|
||||||
|
|
||||||
func findTypeParam(obj types.Object, list *typeparams.TypeParamList, path []byte, seen map[*types.TypeName]bool) []byte {
|
func findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, op byte, seen map[*types.TypeName]bool) []byte {
|
||||||
for i := 0; i < list.Len(); i++ {
|
for i := 0; i < list.Len(); i++ {
|
||||||
tparam := list.At(i)
|
tparam := list.At(i)
|
||||||
path2 := appendOpArg(path, opTypeParam, i)
|
path2 := appendOpArg(path, op, i)
|
||||||
if r := find(obj, tparam, path2, seen); r != nil {
|
if r := find(obj, tparam, path2, seen); r != nil {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@ -576,12 +548,7 @@ func findTypeParam(obj types.Object, list *typeparams.TypeParamList, path []byte
|
|||||||
|
|
||||||
// Object returns the object denoted by path p within the package pkg.
|
// Object returns the object denoted by path p within the package pkg.
|
||||||
func Object(pkg *types.Package, p Path) (types.Object, error) {
|
func Object(pkg *types.Package, p Path) (types.Object, error) {
|
||||||
return object(pkg, string(p), false)
|
pathstr := string(p)
|
||||||
}
|
|
||||||
|
|
||||||
// Note: the skipMethodSorting parameter must match the value of
|
|
||||||
// Encoder.skipMethodSorting used during encoding.
|
|
||||||
func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.Object, error) {
|
|
||||||
if pathstr == "" {
|
if pathstr == "" {
|
||||||
return nil, fmt.Errorf("empty path")
|
return nil, fmt.Errorf("empty path")
|
||||||
}
|
}
|
||||||
@ -605,7 +572,7 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O
|
|||||||
}
|
}
|
||||||
// abstraction of *types.{Named,Signature}
|
// abstraction of *types.{Named,Signature}
|
||||||
type hasTypeParams interface {
|
type hasTypeParams interface {
|
||||||
TypeParams() *typeparams.TypeParamList
|
TypeParams() *types.TypeParamList
|
||||||
}
|
}
|
||||||
// abstraction of *types.{Named,TypeParam}
|
// abstraction of *types.{Named,TypeParam}
|
||||||
type hasObj interface {
|
type hasObj interface {
|
||||||
@ -623,10 +590,10 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O
|
|||||||
code := suffix[0]
|
code := suffix[0]
|
||||||
suffix = suffix[1:]
|
suffix = suffix[1:]
|
||||||
|
|
||||||
// Codes [AFM] have an integer operand.
|
// Codes [AFMTr] have an integer operand.
|
||||||
var index int
|
var index int
|
||||||
switch code {
|
switch code {
|
||||||
case opAt, opField, opMethod, opTypeParam:
|
case opAt, opField, opMethod, opTypeParam, opRecvTypeParam:
|
||||||
rest := strings.TrimLeft(suffix, "0123456789")
|
rest := strings.TrimLeft(suffix, "0123456789")
|
||||||
numerals := suffix[:len(suffix)-len(rest)]
|
numerals := suffix[:len(suffix)-len(rest)]
|
||||||
suffix = rest
|
suffix = rest
|
||||||
@ -659,6 +626,7 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O
|
|||||||
|
|
||||||
// Inv: t != nil, obj == nil
|
// Inv: t != nil, obj == nil
|
||||||
|
|
||||||
|
t = types.Unalias(t)
|
||||||
switch code {
|
switch code {
|
||||||
case opElem:
|
case opElem:
|
||||||
hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map
|
hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map
|
||||||
@ -695,6 +663,16 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O
|
|||||||
}
|
}
|
||||||
t = named.Underlying()
|
t = named.Underlying()
|
||||||
|
|
||||||
|
case opRhs:
|
||||||
|
if alias, ok := t.(*types.Alias); ok {
|
||||||
|
t = aliases.Rhs(alias)
|
||||||
|
} else if false && aliases.Enabled() {
|
||||||
|
// The Enabled check is too expensive, so for now we
|
||||||
|
// simply assume that aliases are not enabled.
|
||||||
|
// TODO(adonovan): replace with "if true {" when go1.24 is assured.
|
||||||
|
return nil, fmt.Errorf("cannot apply %q to %s (got %T, want alias)", code, t, t)
|
||||||
|
}
|
||||||
|
|
||||||
case opTypeParam:
|
case opTypeParam:
|
||||||
hasTypeParams, ok := t.(hasTypeParams) // Named, Signature
|
hasTypeParams, ok := t.(hasTypeParams) // Named, Signature
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -706,8 +684,19 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O
|
|||||||
}
|
}
|
||||||
t = tparams.At(index)
|
t = tparams.At(index)
|
||||||
|
|
||||||
|
case opRecvTypeParam:
|
||||||
|
sig, ok := t.(*types.Signature) // Signature
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("cannot apply %q to %s (got %T, want signature)", code, t, t)
|
||||||
|
}
|
||||||
|
rtparams := sig.RecvTypeParams()
|
||||||
|
if n := rtparams.Len(); index >= n {
|
||||||
|
return nil, fmt.Errorf("tuple index %d out of range [0-%d)", index, n)
|
||||||
|
}
|
||||||
|
t = rtparams.At(index)
|
||||||
|
|
||||||
case opConstraint:
|
case opConstraint:
|
||||||
tparam, ok := t.(*typeparams.TypeParam)
|
tparam, ok := t.(*types.TypeParam)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("cannot apply %q to %s (got %T, want type parameter)", code, t, t)
|
return nil, fmt.Errorf("cannot apply %q to %s (got %T, want type parameter)", code, t, t)
|
||||||
}
|
}
|
||||||
@ -747,12 +736,7 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O
|
|||||||
if index >= t.NumMethods() {
|
if index >= t.NumMethods() {
|
||||||
return nil, fmt.Errorf("method index %d out of range [0-%d)", index, t.NumMethods())
|
return nil, fmt.Errorf("method index %d out of range [0-%d)", index, t.NumMethods())
|
||||||
}
|
}
|
||||||
if skipMethodSorting {
|
obj = t.Method(index)
|
||||||
obj = t.Method(index)
|
|
||||||
} else {
|
|
||||||
methods := namedMethods(t) // (unmemoized)
|
|
||||||
obj = methods[index] // Id-ordered
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("cannot apply %q to %s (got %T, want interface or named)", code, t, t)
|
return nil, fmt.Errorf("cannot apply %q to %s (got %T, want interface or named)", code, t, t)
|
||||||
@ -772,6 +756,10 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if obj == nil {
|
||||||
|
panic(p) // path does not end in an object-valued operator
|
||||||
|
}
|
||||||
|
|
||||||
if obj.Pkg() != pkg {
|
if obj.Pkg() != pkg {
|
||||||
return nil, fmt.Errorf("path denotes %s, which belongs to a different package", obj)
|
return nil, fmt.Errorf("path denotes %s, which belongs to a different package", obj)
|
||||||
}
|
}
|
||||||
@ -779,33 +767,6 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O
|
|||||||
return obj, nil // success
|
return obj, nil // success
|
||||||
}
|
}
|
||||||
|
|
||||||
// namedMethods returns the methods of a Named type in ascending Id order.
|
|
||||||
func namedMethods(named *types.Named) []*types.Func {
|
|
||||||
methods := make([]*types.Func, named.NumMethods())
|
|
||||||
for i := range methods {
|
|
||||||
methods[i] = named.Method(i)
|
|
||||||
}
|
|
||||||
sort.Slice(methods, func(i, j int) bool {
|
|
||||||
return methods[i].Id() < methods[j].Id()
|
|
||||||
})
|
|
||||||
return methods
|
|
||||||
}
|
|
||||||
|
|
||||||
// namedMethods is a memoization of the namedMethods function. Callers must not modify the result.
|
|
||||||
func (enc *Encoder) namedMethods(named *types.Named) []*types.Func {
|
|
||||||
m := enc.namedMethodsMemo
|
|
||||||
if m == nil {
|
|
||||||
m = make(map[*types.Named][]*types.Func)
|
|
||||||
enc.namedMethodsMemo = m
|
|
||||||
}
|
|
||||||
methods, ok := m[named]
|
|
||||||
if !ok {
|
|
||||||
methods = namedMethods(named) // allocates and sorts
|
|
||||||
m[named] = methods
|
|
||||||
}
|
|
||||||
return methods
|
|
||||||
}
|
|
||||||
|
|
||||||
// scopeObjects is a memoization of scope objects.
|
// scopeObjects is a memoization of scope objects.
|
||||||
// Callers must not modify the result.
|
// Callers must not modify the result.
|
||||||
func (enc *Encoder) scopeObjects(scope *types.Scope) []types.Object {
|
func (enc *Encoder) scopeObjects(scope *types.Scope) []types.Object {
|
||||||
|
68
vendor/golang.org/x/tools/go/types/typeutil/callee.go
generated
vendored
Normal file
68
vendor/golang.org/x/tools/go/types/typeutil/callee.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// 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 typeutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/types"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/typeparams"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Callee returns the named target of a function call, if any:
|
||||||
|
// a function, method, builtin, or variable.
|
||||||
|
//
|
||||||
|
// Functions and methods may potentially have type parameters.
|
||||||
|
func Callee(info *types.Info, call *ast.CallExpr) types.Object {
|
||||||
|
fun := ast.Unparen(call.Fun)
|
||||||
|
|
||||||
|
// Look through type instantiation if necessary.
|
||||||
|
isInstance := false
|
||||||
|
switch fun.(type) {
|
||||||
|
case *ast.IndexExpr, *ast.IndexListExpr:
|
||||||
|
// When extracting the callee from an *IndexExpr, we need to check that
|
||||||
|
// it is a *types.Func and not a *types.Var.
|
||||||
|
// Example: Don't match a slice m within the expression `m[0]()`.
|
||||||
|
isInstance = true
|
||||||
|
fun, _, _, _ = typeparams.UnpackIndexExpr(fun)
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj types.Object
|
||||||
|
switch fun := fun.(type) {
|
||||||
|
case *ast.Ident:
|
||||||
|
obj = info.Uses[fun] // type, var, builtin, or declared func
|
||||||
|
case *ast.SelectorExpr:
|
||||||
|
if sel, ok := info.Selections[fun]; ok {
|
||||||
|
obj = sel.Obj() // method or field
|
||||||
|
} else {
|
||||||
|
obj = info.Uses[fun.Sel] // qualified identifier?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, ok := obj.(*types.TypeName); ok {
|
||||||
|
return nil // T(x) is a conversion, not a call
|
||||||
|
}
|
||||||
|
// A Func is required to match instantiations.
|
||||||
|
if _, ok := obj.(*types.Func); isInstance && !ok {
|
||||||
|
return nil // Was not a Func.
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
// StaticCallee returns the target (function or method) of a static function
|
||||||
|
// call, if any. It returns nil for calls to builtins.
|
||||||
|
//
|
||||||
|
// Note: for calls of instantiated functions and methods, StaticCallee returns
|
||||||
|
// the corresponding generic function or method on the generic type.
|
||||||
|
func StaticCallee(info *types.Info, call *ast.CallExpr) *types.Func {
|
||||||
|
if f, ok := Callee(info, call).(*types.Func); ok && !interfaceMethod(f) {
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func interfaceMethod(f *types.Func) bool {
|
||||||
|
recv := f.Type().(*types.Signature).Recv()
|
||||||
|
return recv != nil && types.IsInterface(recv.Type())
|
||||||
|
}
|
30
vendor/golang.org/x/tools/go/types/typeutil/imports.go
generated
vendored
Normal file
30
vendor/golang.org/x/tools/go/types/typeutil/imports.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package typeutil
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
// Dependencies returns all dependencies of the specified packages.
|
||||||
|
//
|
||||||
|
// Dependent packages appear in topological order: if package P imports
|
||||||
|
// package Q, Q appears earlier than P in the result.
|
||||||
|
// The algorithm follows import statements in the order they
|
||||||
|
// appear in the source code, so the result is a total order.
|
||||||
|
func Dependencies(pkgs ...*types.Package) []*types.Package {
|
||||||
|
var result []*types.Package
|
||||||
|
seen := make(map[*types.Package]bool)
|
||||||
|
var visit func(pkgs []*types.Package)
|
||||||
|
visit = func(pkgs []*types.Package) {
|
||||||
|
for _, p := range pkgs {
|
||||||
|
if !seen[p] {
|
||||||
|
seen[p] = true
|
||||||
|
visit(p.Imports())
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visit(pkgs)
|
||||||
|
return result
|
||||||
|
}
|
517
vendor/golang.org/x/tools/go/types/typeutil/map.go
generated
vendored
Normal file
517
vendor/golang.org/x/tools/go/types/typeutil/map.go
generated
vendored
Normal file
@ -0,0 +1,517 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package typeutil defines various utilities for types, such as Map,
|
||||||
|
// a mapping from types.Type to any values.
|
||||||
|
package typeutil // import "golang.org/x/tools/go/types/typeutil"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/typeparams"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Map is a hash-table-based mapping from types (types.Type) to
|
||||||
|
// arbitrary any values. The concrete types that implement
|
||||||
|
// the Type interface are pointers. Since they are not canonicalized,
|
||||||
|
// == cannot be used to check for equivalence, and thus we cannot
|
||||||
|
// simply use a Go map.
|
||||||
|
//
|
||||||
|
// Just as with map[K]V, a nil *Map is a valid empty map.
|
||||||
|
//
|
||||||
|
// Not thread-safe.
|
||||||
|
type Map struct {
|
||||||
|
hasher Hasher // shared by many Maps
|
||||||
|
table map[uint32][]entry // maps hash to bucket; entry.key==nil means unused
|
||||||
|
length int // number of map entries
|
||||||
|
}
|
||||||
|
|
||||||
|
// entry is an entry (key/value association) in a hash bucket.
|
||||||
|
type entry struct {
|
||||||
|
key types.Type
|
||||||
|
value any
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHasher sets the hasher used by Map.
|
||||||
|
//
|
||||||
|
// All Hashers are functionally equivalent but contain internal state
|
||||||
|
// used to cache the results of hashing previously seen types.
|
||||||
|
//
|
||||||
|
// A single Hasher created by MakeHasher() may be shared among many
|
||||||
|
// Maps. This is recommended if the instances have many keys in
|
||||||
|
// common, as it will amortize the cost of hash computation.
|
||||||
|
//
|
||||||
|
// A Hasher may grow without bound as new types are seen. Even when a
|
||||||
|
// type is deleted from the map, the Hasher never shrinks, since other
|
||||||
|
// types in the map may reference the deleted type indirectly.
|
||||||
|
//
|
||||||
|
// Hashers are not thread-safe, and read-only operations such as
|
||||||
|
// Map.Lookup require updates to the hasher, so a full Mutex lock (not a
|
||||||
|
// read-lock) is require around all Map operations if a shared
|
||||||
|
// hasher is accessed from multiple threads.
|
||||||
|
//
|
||||||
|
// If SetHasher is not called, the Map will create a private hasher at
|
||||||
|
// the first call to Insert.
|
||||||
|
func (m *Map) SetHasher(hasher Hasher) {
|
||||||
|
m.hasher = hasher
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete removes the entry with the given key, if any.
|
||||||
|
// It returns true if the entry was found.
|
||||||
|
func (m *Map) Delete(key types.Type) bool {
|
||||||
|
if m != nil && m.table != nil {
|
||||||
|
hash := m.hasher.Hash(key)
|
||||||
|
bucket := m.table[hash]
|
||||||
|
for i, e := range bucket {
|
||||||
|
if e.key != nil && types.Identical(key, e.key) {
|
||||||
|
// We can't compact the bucket as it
|
||||||
|
// would disturb iterators.
|
||||||
|
bucket[i] = entry{}
|
||||||
|
m.length--
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// At returns the map entry for the given key.
|
||||||
|
// The result is nil if the entry is not present.
|
||||||
|
func (m *Map) At(key types.Type) any {
|
||||||
|
if m != nil && m.table != nil {
|
||||||
|
for _, e := range m.table[m.hasher.Hash(key)] {
|
||||||
|
if e.key != nil && types.Identical(key, e.key) {
|
||||||
|
return e.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the map entry for key to val,
|
||||||
|
// and returns the previous entry, if any.
|
||||||
|
func (m *Map) Set(key types.Type, value any) (prev any) {
|
||||||
|
if m.table != nil {
|
||||||
|
hash := m.hasher.Hash(key)
|
||||||
|
bucket := m.table[hash]
|
||||||
|
var hole *entry
|
||||||
|
for i, e := range bucket {
|
||||||
|
if e.key == nil {
|
||||||
|
hole = &bucket[i]
|
||||||
|
} else if types.Identical(key, e.key) {
|
||||||
|
prev = e.value
|
||||||
|
bucket[i].value = value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if hole != nil {
|
||||||
|
*hole = entry{key, value} // overwrite deleted entry
|
||||||
|
} else {
|
||||||
|
m.table[hash] = append(bucket, entry{key, value})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if m.hasher.memo == nil {
|
||||||
|
m.hasher = MakeHasher()
|
||||||
|
}
|
||||||
|
hash := m.hasher.Hash(key)
|
||||||
|
m.table = map[uint32][]entry{hash: {entry{key, value}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.length++
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of map entries.
|
||||||
|
func (m *Map) Len() int {
|
||||||
|
if m != nil {
|
||||||
|
return m.length
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate calls function f on each entry in the map in unspecified order.
|
||||||
|
//
|
||||||
|
// If f should mutate the map, Iterate provides the same guarantees as
|
||||||
|
// Go maps: if f deletes a map entry that Iterate has not yet reached,
|
||||||
|
// f will not be invoked for it, but if f inserts a map entry that
|
||||||
|
// Iterate has not yet reached, whether or not f will be invoked for
|
||||||
|
// it is unspecified.
|
||||||
|
func (m *Map) Iterate(f func(key types.Type, value any)) {
|
||||||
|
if m != nil {
|
||||||
|
for _, bucket := range m.table {
|
||||||
|
for _, e := range bucket {
|
||||||
|
if e.key != nil {
|
||||||
|
f(e.key, e.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns a new slice containing the set of map keys.
|
||||||
|
// The order is unspecified.
|
||||||
|
func (m *Map) Keys() []types.Type {
|
||||||
|
keys := make([]types.Type, 0, m.Len())
|
||||||
|
m.Iterate(func(key types.Type, _ any) {
|
||||||
|
keys = append(keys, key)
|
||||||
|
})
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) toString(values bool) string {
|
||||||
|
if m == nil {
|
||||||
|
return "{}"
|
||||||
|
}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
fmt.Fprint(&buf, "{")
|
||||||
|
sep := ""
|
||||||
|
m.Iterate(func(key types.Type, value any) {
|
||||||
|
fmt.Fprint(&buf, sep)
|
||||||
|
sep = ", "
|
||||||
|
fmt.Fprint(&buf, key)
|
||||||
|
if values {
|
||||||
|
fmt.Fprintf(&buf, ": %q", value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
fmt.Fprint(&buf, "}")
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of the map's entries.
|
||||||
|
// Values are printed using fmt.Sprintf("%v", v).
|
||||||
|
// Order is unspecified.
|
||||||
|
func (m *Map) String() string {
|
||||||
|
return m.toString(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeysString returns a string representation of the map's key set.
|
||||||
|
// Order is unspecified.
|
||||||
|
func (m *Map) KeysString() string {
|
||||||
|
return m.toString(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Hasher
|
||||||
|
|
||||||
|
// A Hasher maps each type to its hash value.
|
||||||
|
// For efficiency, a hasher uses memoization; thus its memory
|
||||||
|
// footprint grows monotonically over time.
|
||||||
|
// Hashers are not thread-safe.
|
||||||
|
// Hashers have reference semantics.
|
||||||
|
// Call MakeHasher to create a Hasher.
|
||||||
|
type Hasher struct {
|
||||||
|
memo map[types.Type]uint32
|
||||||
|
|
||||||
|
// ptrMap records pointer identity.
|
||||||
|
ptrMap map[any]uint32
|
||||||
|
|
||||||
|
// sigTParams holds type parameters from the signature being hashed.
|
||||||
|
// Signatures are considered identical modulo renaming of type parameters, so
|
||||||
|
// within the scope of a signature type the identity of the signature's type
|
||||||
|
// parameters is just their index.
|
||||||
|
//
|
||||||
|
// Since the language does not currently support referring to uninstantiated
|
||||||
|
// generic types or functions, and instantiated signatures do not have type
|
||||||
|
// parameter lists, we should never encounter a second non-empty type
|
||||||
|
// parameter list when hashing a generic signature.
|
||||||
|
sigTParams *types.TypeParamList
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeHasher returns a new Hasher instance.
|
||||||
|
func MakeHasher() Hasher {
|
||||||
|
return Hasher{
|
||||||
|
memo: make(map[types.Type]uint32),
|
||||||
|
ptrMap: make(map[any]uint32),
|
||||||
|
sigTParams: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash computes a hash value for the given type t such that
|
||||||
|
// Identical(t, t') => Hash(t) == Hash(t').
|
||||||
|
func (h Hasher) Hash(t types.Type) uint32 {
|
||||||
|
hash, ok := h.memo[t]
|
||||||
|
if !ok {
|
||||||
|
hash = h.hashFor(t)
|
||||||
|
h.memo[t] = hash
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashString computes the Fowler–Noll–Vo hash of s.
|
||||||
|
func hashString(s string) uint32 {
|
||||||
|
var h uint32
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
h ^= uint32(s[i])
|
||||||
|
h *= 16777619
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashFor computes the hash of t.
|
||||||
|
func (h Hasher) hashFor(t types.Type) uint32 {
|
||||||
|
// See Identical for rationale.
|
||||||
|
switch t := t.(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
return uint32(t.Kind())
|
||||||
|
|
||||||
|
case *types.Alias:
|
||||||
|
return h.Hash(types.Unalias(t))
|
||||||
|
|
||||||
|
case *types.Array:
|
||||||
|
return 9043 + 2*uint32(t.Len()) + 3*h.Hash(t.Elem())
|
||||||
|
|
||||||
|
case *types.Slice:
|
||||||
|
return 9049 + 2*h.Hash(t.Elem())
|
||||||
|
|
||||||
|
case *types.Struct:
|
||||||
|
var hash uint32 = 9059
|
||||||
|
for i, n := 0, t.NumFields(); i < n; i++ {
|
||||||
|
f := t.Field(i)
|
||||||
|
if f.Anonymous() {
|
||||||
|
hash += 8861
|
||||||
|
}
|
||||||
|
hash += hashString(t.Tag(i))
|
||||||
|
hash += hashString(f.Name()) // (ignore f.Pkg)
|
||||||
|
hash += h.Hash(f.Type())
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
|
||||||
|
case *types.Pointer:
|
||||||
|
return 9067 + 2*h.Hash(t.Elem())
|
||||||
|
|
||||||
|
case *types.Signature:
|
||||||
|
var hash uint32 = 9091
|
||||||
|
if t.Variadic() {
|
||||||
|
hash *= 8863
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a separate hasher for types inside of the signature, where type
|
||||||
|
// parameter identity is modified to be (index, constraint). We must use a
|
||||||
|
// new memo for this hasher as type identity may be affected by this
|
||||||
|
// masking. For example, in func[T any](*T), the identity of *T depends on
|
||||||
|
// whether we are mapping the argument in isolation, or recursively as part
|
||||||
|
// of hashing the signature.
|
||||||
|
//
|
||||||
|
// We should never encounter a generic signature while hashing another
|
||||||
|
// generic signature, but defensively set sigTParams only if h.mask is
|
||||||
|
// unset.
|
||||||
|
tparams := t.TypeParams()
|
||||||
|
if h.sigTParams == nil && tparams.Len() != 0 {
|
||||||
|
h = Hasher{
|
||||||
|
// There may be something more efficient than discarding the existing
|
||||||
|
// memo, but it would require detecting whether types are 'tainted' by
|
||||||
|
// references to type parameters.
|
||||||
|
memo: make(map[types.Type]uint32),
|
||||||
|
// Re-using ptrMap ensures that pointer identity is preserved in this
|
||||||
|
// hasher.
|
||||||
|
ptrMap: h.ptrMap,
|
||||||
|
sigTParams: tparams,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < tparams.Len(); i++ {
|
||||||
|
tparam := tparams.At(i)
|
||||||
|
hash += 7 * h.Hash(tparam.Constraint())
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results())
|
||||||
|
|
||||||
|
case *types.Union:
|
||||||
|
return h.hashUnion(t)
|
||||||
|
|
||||||
|
case *types.Interface:
|
||||||
|
// Interfaces are identical if they have the same set of methods, with
|
||||||
|
// identical names and types, and they have the same set of type
|
||||||
|
// restrictions. See go/types.identical for more details.
|
||||||
|
var hash uint32 = 9103
|
||||||
|
|
||||||
|
// Hash methods.
|
||||||
|
for i, n := 0, t.NumMethods(); i < n; i++ {
|
||||||
|
// Method order is not significant.
|
||||||
|
// Ignore m.Pkg().
|
||||||
|
m := t.Method(i)
|
||||||
|
// Use shallow hash on method signature to
|
||||||
|
// avoid anonymous interface cycles.
|
||||||
|
hash += 3*hashString(m.Name()) + 5*h.shallowHash(m.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash type restrictions.
|
||||||
|
terms, err := typeparams.InterfaceTermSet(t)
|
||||||
|
// if err != nil t has invalid type restrictions.
|
||||||
|
if err == nil {
|
||||||
|
hash += h.hashTermSet(terms)
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash
|
||||||
|
|
||||||
|
case *types.Map:
|
||||||
|
return 9109 + 2*h.Hash(t.Key()) + 3*h.Hash(t.Elem())
|
||||||
|
|
||||||
|
case *types.Chan:
|
||||||
|
return 9127 + 2*uint32(t.Dir()) + 3*h.Hash(t.Elem())
|
||||||
|
|
||||||
|
case *types.Named:
|
||||||
|
hash := h.hashPtr(t.Obj())
|
||||||
|
targs := t.TypeArgs()
|
||||||
|
for i := 0; i < targs.Len(); i++ {
|
||||||
|
targ := targs.At(i)
|
||||||
|
hash += 2 * h.Hash(targ)
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
|
||||||
|
case *types.TypeParam:
|
||||||
|
return h.hashTypeParam(t)
|
||||||
|
|
||||||
|
case *types.Tuple:
|
||||||
|
return h.hashTuple(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
panic(fmt.Sprintf("%T: %v", t, t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Hasher) hashTuple(tuple *types.Tuple) uint32 {
|
||||||
|
// See go/types.identicalTypes for rationale.
|
||||||
|
n := tuple.Len()
|
||||||
|
hash := 9137 + 2*uint32(n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
hash += 3 * h.Hash(tuple.At(i).Type())
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Hasher) hashUnion(t *types.Union) uint32 {
|
||||||
|
// Hash type restrictions.
|
||||||
|
terms, err := typeparams.UnionTermSet(t)
|
||||||
|
// if err != nil t has invalid type restrictions. Fall back on a non-zero
|
||||||
|
// hash.
|
||||||
|
if err != nil {
|
||||||
|
return 9151
|
||||||
|
}
|
||||||
|
return h.hashTermSet(terms)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Hasher) hashTermSet(terms []*types.Term) uint32 {
|
||||||
|
hash := 9157 + 2*uint32(len(terms))
|
||||||
|
for _, term := range terms {
|
||||||
|
// term order is not significant.
|
||||||
|
termHash := h.Hash(term.Type())
|
||||||
|
if term.Tilde() {
|
||||||
|
termHash *= 9161
|
||||||
|
}
|
||||||
|
hash += 3 * termHash
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashTypeParam returns a hash of the type parameter t, with a hash value
|
||||||
|
// depending on whether t is contained in h.sigTParams.
|
||||||
|
//
|
||||||
|
// If h.sigTParams is set and contains t, then we are in the process of hashing
|
||||||
|
// a signature, and the hash value of t must depend only on t's index and
|
||||||
|
// constraint: signatures are considered identical modulo type parameter
|
||||||
|
// renaming. To avoid infinite recursion, we only hash the type parameter
|
||||||
|
// index, and rely on types.Identical to handle signatures where constraints
|
||||||
|
// are not identical.
|
||||||
|
//
|
||||||
|
// Otherwise the hash of t depends only on t's pointer identity.
|
||||||
|
func (h Hasher) hashTypeParam(t *types.TypeParam) uint32 {
|
||||||
|
if h.sigTParams != nil {
|
||||||
|
i := t.Index()
|
||||||
|
if i >= 0 && i < h.sigTParams.Len() && t == h.sigTParams.At(i) {
|
||||||
|
return 9173 + 3*uint32(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return h.hashPtr(t.Obj())
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashPtr hashes the pointer identity of ptr. It uses h.ptrMap to ensure that
|
||||||
|
// pointers values are not dependent on the GC.
|
||||||
|
func (h Hasher) hashPtr(ptr any) uint32 {
|
||||||
|
if hash, ok := h.ptrMap[ptr]; ok {
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
hash := uint32(reflect.ValueOf(ptr).Pointer())
|
||||||
|
h.ptrMap[ptr] = hash
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// shallowHash computes a hash of t without looking at any of its
|
||||||
|
// element Types, to avoid potential anonymous cycles in the types of
|
||||||
|
// interface methods.
|
||||||
|
//
|
||||||
|
// When an unnamed non-empty interface type appears anywhere among the
|
||||||
|
// arguments or results of an interface method, there is a potential
|
||||||
|
// for endless recursion. Consider:
|
||||||
|
//
|
||||||
|
// type X interface { m() []*interface { X } }
|
||||||
|
//
|
||||||
|
// The problem is that the Methods of the interface in m's result type
|
||||||
|
// include m itself; there is no mention of the named type X that
|
||||||
|
// might help us break the cycle.
|
||||||
|
// (See comment in go/types.identical, case *Interface, for more.)
|
||||||
|
func (h Hasher) shallowHash(t types.Type) uint32 {
|
||||||
|
// t is the type of an interface method (Signature),
|
||||||
|
// its params or results (Tuples), or their immediate
|
||||||
|
// elements (mostly Slice, Pointer, Basic, Named),
|
||||||
|
// so there's no need to optimize anything else.
|
||||||
|
switch t := t.(type) {
|
||||||
|
case *types.Alias:
|
||||||
|
return h.shallowHash(types.Unalias(t))
|
||||||
|
|
||||||
|
case *types.Signature:
|
||||||
|
var hash uint32 = 604171
|
||||||
|
if t.Variadic() {
|
||||||
|
hash *= 971767
|
||||||
|
}
|
||||||
|
// The Signature/Tuple recursion is always finite
|
||||||
|
// and invariably shallow.
|
||||||
|
return hash + 1062599*h.shallowHash(t.Params()) + 1282529*h.shallowHash(t.Results())
|
||||||
|
|
||||||
|
case *types.Tuple:
|
||||||
|
n := t.Len()
|
||||||
|
hash := 9137 + 2*uint32(n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
hash += 53471161 * h.shallowHash(t.At(i).Type())
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
|
||||||
|
case *types.Basic:
|
||||||
|
return 45212177 * uint32(t.Kind())
|
||||||
|
|
||||||
|
case *types.Array:
|
||||||
|
return 1524181 + 2*uint32(t.Len())
|
||||||
|
|
||||||
|
case *types.Slice:
|
||||||
|
return 2690201
|
||||||
|
|
||||||
|
case *types.Struct:
|
||||||
|
return 3326489
|
||||||
|
|
||||||
|
case *types.Pointer:
|
||||||
|
return 4393139
|
||||||
|
|
||||||
|
case *types.Union:
|
||||||
|
return 562448657
|
||||||
|
|
||||||
|
case *types.Interface:
|
||||||
|
return 2124679 // no recursion here
|
||||||
|
|
||||||
|
case *types.Map:
|
||||||
|
return 9109
|
||||||
|
|
||||||
|
case *types.Chan:
|
||||||
|
return 9127
|
||||||
|
|
||||||
|
case *types.Named:
|
||||||
|
return h.hashPtr(t.Obj())
|
||||||
|
|
||||||
|
case *types.TypeParam:
|
||||||
|
return h.hashPtr(t.Obj())
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("shallowHash: %T: %v", t, t))
|
||||||
|
}
|
71
vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go
generated
vendored
Normal file
71
vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This file implements a cache of method sets.
|
||||||
|
|
||||||
|
package typeutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A MethodSetCache records the method set of each type T for which
|
||||||
|
// MethodSet(T) is called so that repeat queries are fast.
|
||||||
|
// The zero value is a ready-to-use cache instance.
|
||||||
|
type MethodSetCache struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
named map[*types.Named]struct{ value, pointer *types.MethodSet } // method sets for named N and *N
|
||||||
|
others map[types.Type]*types.MethodSet // all other types
|
||||||
|
}
|
||||||
|
|
||||||
|
// MethodSet returns the method set of type T. It is thread-safe.
|
||||||
|
//
|
||||||
|
// If cache is nil, this function is equivalent to types.NewMethodSet(T).
|
||||||
|
// Utility functions can thus expose an optional *MethodSetCache
|
||||||
|
// parameter to clients that care about performance.
|
||||||
|
func (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet {
|
||||||
|
if cache == nil {
|
||||||
|
return types.NewMethodSet(T)
|
||||||
|
}
|
||||||
|
cache.mu.Lock()
|
||||||
|
defer cache.mu.Unlock()
|
||||||
|
|
||||||
|
switch T := types.Unalias(T).(type) {
|
||||||
|
case *types.Named:
|
||||||
|
return cache.lookupNamed(T).value
|
||||||
|
|
||||||
|
case *types.Pointer:
|
||||||
|
if N, ok := types.Unalias(T.Elem()).(*types.Named); ok {
|
||||||
|
return cache.lookupNamed(N).pointer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// all other types
|
||||||
|
// (The map uses pointer equivalence, not type identity.)
|
||||||
|
mset := cache.others[T]
|
||||||
|
if mset == nil {
|
||||||
|
mset = types.NewMethodSet(T)
|
||||||
|
if cache.others == nil {
|
||||||
|
cache.others = make(map[types.Type]*types.MethodSet)
|
||||||
|
}
|
||||||
|
cache.others[T] = mset
|
||||||
|
}
|
||||||
|
return mset
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cache *MethodSetCache) lookupNamed(named *types.Named) struct{ value, pointer *types.MethodSet } {
|
||||||
|
if cache.named == nil {
|
||||||
|
cache.named = make(map[*types.Named]struct{ value, pointer *types.MethodSet })
|
||||||
|
}
|
||||||
|
// Avoid recomputing mset(*T) for each distinct Pointer
|
||||||
|
// instance whose underlying type is a named type.
|
||||||
|
msets, ok := cache.named[named]
|
||||||
|
if !ok {
|
||||||
|
msets.value = types.NewMethodSet(named)
|
||||||
|
msets.pointer = types.NewMethodSet(types.NewPointer(named))
|
||||||
|
cache.named[named] = msets
|
||||||
|
}
|
||||||
|
return msets
|
||||||
|
}
|
53
vendor/golang.org/x/tools/go/types/typeutil/ui.go
generated
vendored
Normal file
53
vendor/golang.org/x/tools/go/types/typeutil/ui.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package typeutil
|
||||||
|
|
||||||
|
// This file defines utilities for user interfaces that display types.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IntuitiveMethodSet returns the intuitive method set of a type T,
|
||||||
|
// which is the set of methods you can call on an addressable value of
|
||||||
|
// that type.
|
||||||
|
//
|
||||||
|
// The result always contains MethodSet(T), and is exactly MethodSet(T)
|
||||||
|
// for interface types and for pointer-to-concrete types.
|
||||||
|
// For all other concrete types T, the result additionally
|
||||||
|
// contains each method belonging to *T if there is no identically
|
||||||
|
// named method on T itself.
|
||||||
|
//
|
||||||
|
// This corresponds to user intuition about method sets;
|
||||||
|
// this function is intended only for user interfaces.
|
||||||
|
//
|
||||||
|
// The order of the result is as for types.MethodSet(T).
|
||||||
|
func IntuitiveMethodSet(T types.Type, msets *MethodSetCache) []*types.Selection {
|
||||||
|
isPointerToConcrete := func(T types.Type) bool {
|
||||||
|
ptr, ok := types.Unalias(T).(*types.Pointer)
|
||||||
|
return ok && !types.IsInterface(ptr.Elem())
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []*types.Selection
|
||||||
|
mset := msets.MethodSet(T)
|
||||||
|
if types.IsInterface(T) || isPointerToConcrete(T) {
|
||||||
|
for i, n := 0, mset.Len(); i < n; i++ {
|
||||||
|
result = append(result, mset.At(i))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// T is some other concrete type.
|
||||||
|
// Report methods of T and *T, preferring those of T.
|
||||||
|
pmset := msets.MethodSet(types.NewPointer(T))
|
||||||
|
for i, n := 0, pmset.Len(); i < n; i++ {
|
||||||
|
meth := pmset.At(i)
|
||||||
|
if m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil {
|
||||||
|
meth = m
|
||||||
|
}
|
||||||
|
result = append(result, meth)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
38
vendor/golang.org/x/tools/internal/aliases/aliases.go
generated
vendored
Normal file
38
vendor/golang.org/x/tools/internal/aliases/aliases.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package aliases
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Package aliases defines backward compatible shims
|
||||||
|
// for the types.Alias type representation added in 1.22.
|
||||||
|
// This defines placeholders for x/tools until 1.26.
|
||||||
|
|
||||||
|
// NewAlias creates a new TypeName in Package pkg that
|
||||||
|
// is an alias for the type rhs.
|
||||||
|
//
|
||||||
|
// The enabled parameter determines whether the resulting [TypeName]'s
|
||||||
|
// type is an [types.Alias]. Its value must be the result of a call to
|
||||||
|
// [Enabled], which computes the effective value of
|
||||||
|
// GODEBUG=gotypesalias=... by invoking the type checker. The Enabled
|
||||||
|
// function is expensive and should be called once per task (e.g.
|
||||||
|
// package import), not once per call to NewAlias.
|
||||||
|
//
|
||||||
|
// Precondition: enabled || len(tparams)==0.
|
||||||
|
// If materialized aliases are disabled, there must not be any type parameters.
|
||||||
|
func NewAlias(enabled bool, pos token.Pos, pkg *types.Package, name string, rhs types.Type, tparams []*types.TypeParam) *types.TypeName {
|
||||||
|
if enabled {
|
||||||
|
tname := types.NewTypeName(pos, pkg, name, nil)
|
||||||
|
SetTypeParams(types.NewAlias(tname, rhs), tparams)
|
||||||
|
return tname
|
||||||
|
}
|
||||||
|
if len(tparams) > 0 {
|
||||||
|
panic("cannot create an alias with type parameters when gotypesalias is not enabled")
|
||||||
|
}
|
||||||
|
return types.NewTypeName(pos, pkg, name, rhs)
|
||||||
|
}
|
80
vendor/golang.org/x/tools/internal/aliases/aliases_go122.go
generated
vendored
Normal file
80
vendor/golang.org/x/tools/internal/aliases/aliases_go122.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package aliases
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Rhs returns the type on the right-hand side of the alias declaration.
|
||||||
|
func Rhs(alias *types.Alias) types.Type {
|
||||||
|
if alias, ok := any(alias).(interface{ Rhs() types.Type }); ok {
|
||||||
|
return alias.Rhs() // go1.23+
|
||||||
|
}
|
||||||
|
|
||||||
|
// go1.22's Alias didn't have the Rhs method,
|
||||||
|
// so Unalias is the best we can do.
|
||||||
|
return types.Unalias(alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeParams returns the type parameter list of the alias.
|
||||||
|
func TypeParams(alias *types.Alias) *types.TypeParamList {
|
||||||
|
if alias, ok := any(alias).(interface{ TypeParams() *types.TypeParamList }); ok {
|
||||||
|
return alias.TypeParams() // go1.23+
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTypeParams sets the type parameters of the alias type.
|
||||||
|
func SetTypeParams(alias *types.Alias, tparams []*types.TypeParam) {
|
||||||
|
if alias, ok := any(alias).(interface {
|
||||||
|
SetTypeParams(tparams []*types.TypeParam)
|
||||||
|
}); ok {
|
||||||
|
alias.SetTypeParams(tparams) // go1.23+
|
||||||
|
} else if len(tparams) > 0 {
|
||||||
|
panic("cannot set type parameters of an Alias type in go1.22")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeArgs returns the type arguments used to instantiate the Alias type.
|
||||||
|
func TypeArgs(alias *types.Alias) *types.TypeList {
|
||||||
|
if alias, ok := any(alias).(interface{ TypeArgs() *types.TypeList }); ok {
|
||||||
|
return alias.TypeArgs() // go1.23+
|
||||||
|
}
|
||||||
|
return nil // empty (go1.22)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Origin returns the generic Alias type of which alias is an instance.
|
||||||
|
// If alias is not an instance of a generic alias, Origin returns alias.
|
||||||
|
func Origin(alias *types.Alias) *types.Alias {
|
||||||
|
if alias, ok := any(alias).(interface{ Origin() *types.Alias }); ok {
|
||||||
|
return alias.Origin() // go1.23+
|
||||||
|
}
|
||||||
|
return alias // not an instance of a generic alias (go1.22)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enabled reports whether [NewAlias] should create [types.Alias] types.
|
||||||
|
//
|
||||||
|
// This function is expensive! Call it sparingly.
|
||||||
|
func Enabled() bool {
|
||||||
|
// The only reliable way to compute the answer is to invoke go/types.
|
||||||
|
// We don't parse the GODEBUG environment variable, because
|
||||||
|
// (a) it's tricky to do so in a manner that is consistent
|
||||||
|
// with the godebug package; in particular, a simple
|
||||||
|
// substring check is not good enough. The value is a
|
||||||
|
// rightmost-wins list of options. But more importantly:
|
||||||
|
// (b) it is impossible to detect changes to the effective
|
||||||
|
// setting caused by os.Setenv("GODEBUG"), as happens in
|
||||||
|
// many tests. Therefore any attempt to cache the result
|
||||||
|
// is just incorrect.
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", parser.SkipObjectResolution)
|
||||||
|
pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil)
|
||||||
|
_, enabled := pkg.Scope().Lookup("A").Type().(*types.Alias)
|
||||||
|
return enabled
|
||||||
|
}
|
21
vendor/golang.org/x/tools/internal/event/keys/util.go
generated
vendored
Normal file
21
vendor/golang.org/x/tools/internal/event/keys/util.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2023 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 keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Join returns a canonical join of the keys in S:
|
||||||
|
// a sorted comma-separated string list.
|
||||||
|
func Join[S ~[]T, T ~string](s S) string {
|
||||||
|
strs := make([]string, 0, len(s))
|
||||||
|
for _, v := range s {
|
||||||
|
strs = append(strs, string(v))
|
||||||
|
}
|
||||||
|
sort.Strings(strs)
|
||||||
|
return strings.Join(strs, ",")
|
||||||
|
}
|
59
vendor/golang.org/x/tools/internal/event/tag/tag.go
generated
vendored
59
vendor/golang.org/x/tools/internal/event/tag/tag.go
generated
vendored
@ -1,59 +0,0 @@
|
|||||||
// Copyright 2019 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 tag provides the labels used for telemetry throughout gopls.
|
|
||||||
package tag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/tools/internal/event/keys"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// create the label keys we use
|
|
||||||
Method = keys.NewString("method", "")
|
|
||||||
StatusCode = keys.NewString("status.code", "")
|
|
||||||
StatusMessage = keys.NewString("status.message", "")
|
|
||||||
RPCID = keys.NewString("id", "")
|
|
||||||
RPCDirection = keys.NewString("direction", "")
|
|
||||||
File = keys.NewString("file", "")
|
|
||||||
Directory = keys.New("directory", "")
|
|
||||||
URI = keys.New("URI", "")
|
|
||||||
Package = keys.NewString("package", "") // sorted comma-separated list of Package IDs
|
|
||||||
PackagePath = keys.NewString("package_path", "")
|
|
||||||
Query = keys.New("query", "")
|
|
||||||
Snapshot = keys.NewUInt64("snapshot", "")
|
|
||||||
Operation = keys.NewString("operation", "")
|
|
||||||
|
|
||||||
Position = keys.New("position", "")
|
|
||||||
Category = keys.NewString("category", "")
|
|
||||||
PackageCount = keys.NewInt("packages", "")
|
|
||||||
Files = keys.New("files", "")
|
|
||||||
Port = keys.NewInt("port", "")
|
|
||||||
Type = keys.New("type", "")
|
|
||||||
HoverKind = keys.NewString("hoverkind", "")
|
|
||||||
|
|
||||||
NewServer = keys.NewString("new_server", "A new server was added")
|
|
||||||
EndServer = keys.NewString("end_server", "A server was shut down")
|
|
||||||
|
|
||||||
ServerID = keys.NewString("server", "The server ID an event is related to")
|
|
||||||
Logfile = keys.NewString("logfile", "")
|
|
||||||
DebugAddress = keys.NewString("debug_address", "")
|
|
||||||
GoplsPath = keys.NewString("gopls_path", "")
|
|
||||||
ClientID = keys.NewString("client_id", "")
|
|
||||||
|
|
||||||
Level = keys.NewInt("level", "The logging level")
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// create the stats we measure
|
|
||||||
Started = keys.NewInt64("started", "Count of started RPCs.")
|
|
||||||
ReceivedBytes = keys.NewInt64("received_bytes", "Bytes received.") //, unit.Bytes)
|
|
||||||
SentBytes = keys.NewInt64("sent_bytes", "Bytes sent.") //, unit.Bytes)
|
|
||||||
Latency = keys.NewFloat64("latency_ms", "Elapsed time in milliseconds") //, unit.Milliseconds)
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
Inbound = "in"
|
|
||||||
Outbound = "out"
|
|
||||||
)
|
|
61
vendor/golang.org/x/tools/internal/gcimporter/bimport.go
generated
vendored
61
vendor/golang.org/x/tools/internal/gcimporter/bimport.go
generated
vendored
@ -87,64 +87,3 @@ func chanDir(d int) types.ChanDir {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var predeclOnce sync.Once
|
|
||||||
var predecl []types.Type // initialized lazily
|
|
||||||
|
|
||||||
func predeclared() []types.Type {
|
|
||||||
predeclOnce.Do(func() {
|
|
||||||
// initialize lazily to be sure that all
|
|
||||||
// elements have been initialized before
|
|
||||||
predecl = []types.Type{ // basic types
|
|
||||||
types.Typ[types.Bool],
|
|
||||||
types.Typ[types.Int],
|
|
||||||
types.Typ[types.Int8],
|
|
||||||
types.Typ[types.Int16],
|
|
||||||
types.Typ[types.Int32],
|
|
||||||
types.Typ[types.Int64],
|
|
||||||
types.Typ[types.Uint],
|
|
||||||
types.Typ[types.Uint8],
|
|
||||||
types.Typ[types.Uint16],
|
|
||||||
types.Typ[types.Uint32],
|
|
||||||
types.Typ[types.Uint64],
|
|
||||||
types.Typ[types.Uintptr],
|
|
||||||
types.Typ[types.Float32],
|
|
||||||
types.Typ[types.Float64],
|
|
||||||
types.Typ[types.Complex64],
|
|
||||||
types.Typ[types.Complex128],
|
|
||||||
types.Typ[types.String],
|
|
||||||
|
|
||||||
// basic type aliases
|
|
||||||
types.Universe.Lookup("byte").Type(),
|
|
||||||
types.Universe.Lookup("rune").Type(),
|
|
||||||
|
|
||||||
// error
|
|
||||||
types.Universe.Lookup("error").Type(),
|
|
||||||
|
|
||||||
// untyped types
|
|
||||||
types.Typ[types.UntypedBool],
|
|
||||||
types.Typ[types.UntypedInt],
|
|
||||||
types.Typ[types.UntypedRune],
|
|
||||||
types.Typ[types.UntypedFloat],
|
|
||||||
types.Typ[types.UntypedComplex],
|
|
||||||
types.Typ[types.UntypedString],
|
|
||||||
types.Typ[types.UntypedNil],
|
|
||||||
|
|
||||||
// package unsafe
|
|
||||||
types.Typ[types.UnsafePointer],
|
|
||||||
|
|
||||||
// invalid type
|
|
||||||
types.Typ[types.Invalid], // only appears in packages with errors
|
|
||||||
|
|
||||||
// used internally by gc; never used by this package or in .a files
|
|
||||||
anyType{},
|
|
||||||
}
|
|
||||||
predecl = append(predecl, additionalPredeclared()...)
|
|
||||||
})
|
|
||||||
return predecl
|
|
||||||
}
|
|
||||||
|
|
||||||
type anyType struct{}
|
|
||||||
|
|
||||||
func (t anyType) Underlying() types.Type { return t }
|
|
||||||
func (t anyType) String() string { return "any" }
|
|
||||||
|
18
vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go
generated
vendored
18
vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go
generated
vendored
@ -232,14 +232,19 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
|
|||||||
// Select appropriate importer.
|
// Select appropriate importer.
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
switch data[0] {
|
switch data[0] {
|
||||||
case 'v', 'c', 'd': // binary, till go1.10
|
case 'v', 'c', 'd':
|
||||||
|
// binary: emitted by cmd/compile till go1.10; obsolete.
|
||||||
return nil, fmt.Errorf("binary (%c) import format is no longer supported", data[0])
|
return nil, fmt.Errorf("binary (%c) import format is no longer supported", data[0])
|
||||||
|
|
||||||
case 'i': // indexed, till go1.19
|
case 'i':
|
||||||
|
// indexed: emitted by cmd/compile till go1.19;
|
||||||
|
// now used only for serializing go/types.
|
||||||
|
// See https://github.com/golang/go/issues/69491.
|
||||||
_, pkg, err := IImportData(fset, packages, data[1:], id)
|
_, pkg, err := IImportData(fset, packages, data[1:], id)
|
||||||
return pkg, err
|
return pkg, err
|
||||||
|
|
||||||
case 'u': // unified, from go1.20
|
case 'u':
|
||||||
|
// unified: emitted by cmd/compile since go1.20.
|
||||||
_, pkg, err := UImportData(fset, packages, data[1:size], id)
|
_, pkg, err := UImportData(fset, packages, data[1:size], id)
|
||||||
return pkg, err
|
return pkg, err
|
||||||
|
|
||||||
@ -259,13 +264,6 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func deref(typ types.Type) types.Type {
|
|
||||||
if p, _ := typ.(*types.Pointer); p != nil {
|
|
||||||
return p.Elem()
|
|
||||||
}
|
|
||||||
return typ
|
|
||||||
}
|
|
||||||
|
|
||||||
type byPath []*types.Package
|
type byPath []*types.Package
|
||||||
|
|
||||||
func (a byPath) Len() int { return len(a) }
|
func (a byPath) Len() int { return len(a) }
|
||||||
|
310
vendor/golang.org/x/tools/internal/gcimporter/iexport.go
generated
vendored
310
vendor/golang.org/x/tools/internal/gcimporter/iexport.go
generated
vendored
@ -2,9 +2,227 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
// Indexed binary package export.
|
// Indexed package export.
|
||||||
// This file was derived from $GOROOT/src/cmd/compile/internal/gc/iexport.go;
|
//
|
||||||
// see that file for specification of the format.
|
// The indexed export data format is an evolution of the previous
|
||||||
|
// binary export data format. Its chief contribution is introducing an
|
||||||
|
// index table, which allows efficient random access of individual
|
||||||
|
// declarations and inline function bodies. In turn, this allows
|
||||||
|
// avoiding unnecessary work for compilation units that import large
|
||||||
|
// packages.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// The top-level data format is structured as:
|
||||||
|
//
|
||||||
|
// Header struct {
|
||||||
|
// Tag byte // 'i'
|
||||||
|
// Version uvarint
|
||||||
|
// StringSize uvarint
|
||||||
|
// DataSize uvarint
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Strings [StringSize]byte
|
||||||
|
// Data [DataSize]byte
|
||||||
|
//
|
||||||
|
// MainIndex []struct{
|
||||||
|
// PkgPath stringOff
|
||||||
|
// PkgName stringOff
|
||||||
|
// PkgHeight uvarint
|
||||||
|
//
|
||||||
|
// Decls []struct{
|
||||||
|
// Name stringOff
|
||||||
|
// Offset declOff
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Fingerprint [8]byte
|
||||||
|
//
|
||||||
|
// uvarint means a uint64 written out using uvarint encoding.
|
||||||
|
//
|
||||||
|
// []T means a uvarint followed by that many T objects. In other
|
||||||
|
// words:
|
||||||
|
//
|
||||||
|
// Len uvarint
|
||||||
|
// Elems [Len]T
|
||||||
|
//
|
||||||
|
// stringOff means a uvarint that indicates an offset within the
|
||||||
|
// Strings section. At that offset is another uvarint, followed by
|
||||||
|
// that many bytes, which form the string value.
|
||||||
|
//
|
||||||
|
// declOff means a uvarint that indicates an offset within the Data
|
||||||
|
// section where the associated declaration can be found.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// There are five kinds of declarations, distinguished by their first
|
||||||
|
// byte:
|
||||||
|
//
|
||||||
|
// type Var struct {
|
||||||
|
// Tag byte // 'V'
|
||||||
|
// Pos Pos
|
||||||
|
// Type typeOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type Func struct {
|
||||||
|
// Tag byte // 'F' or 'G'
|
||||||
|
// Pos Pos
|
||||||
|
// TypeParams []typeOff // only present if Tag == 'G'
|
||||||
|
// Signature Signature
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type Const struct {
|
||||||
|
// Tag byte // 'C'
|
||||||
|
// Pos Pos
|
||||||
|
// Value Value
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type Type struct {
|
||||||
|
// Tag byte // 'T' or 'U'
|
||||||
|
// Pos Pos
|
||||||
|
// TypeParams []typeOff // only present if Tag == 'U'
|
||||||
|
// Underlying typeOff
|
||||||
|
//
|
||||||
|
// Methods []struct{ // omitted if Underlying is an interface type
|
||||||
|
// Pos Pos
|
||||||
|
// Name stringOff
|
||||||
|
// Recv Param
|
||||||
|
// Signature Signature
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type Alias struct {
|
||||||
|
// Tag byte // 'A' or 'B'
|
||||||
|
// Pos Pos
|
||||||
|
// TypeParams []typeOff // only present if Tag == 'B'
|
||||||
|
// Type typeOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // "Automatic" declaration of each typeparam
|
||||||
|
// type TypeParam struct {
|
||||||
|
// Tag byte // 'P'
|
||||||
|
// Pos Pos
|
||||||
|
// Implicit bool
|
||||||
|
// Constraint typeOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// typeOff means a uvarint that either indicates a predeclared type,
|
||||||
|
// or an offset into the Data section. If the uvarint is less than
|
||||||
|
// predeclReserved, then it indicates the index into the predeclared
|
||||||
|
// types list (see predeclared in bexport.go for order). Otherwise,
|
||||||
|
// subtracting predeclReserved yields the offset of a type descriptor.
|
||||||
|
//
|
||||||
|
// Value means a type, kind, and type-specific value. See
|
||||||
|
// (*exportWriter).value for details.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// There are twelve kinds of type descriptors, distinguished by an itag:
|
||||||
|
//
|
||||||
|
// type DefinedType struct {
|
||||||
|
// Tag itag // definedType
|
||||||
|
// Name stringOff
|
||||||
|
// PkgPath stringOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type PointerType struct {
|
||||||
|
// Tag itag // pointerType
|
||||||
|
// Elem typeOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type SliceType struct {
|
||||||
|
// Tag itag // sliceType
|
||||||
|
// Elem typeOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type ArrayType struct {
|
||||||
|
// Tag itag // arrayType
|
||||||
|
// Len uint64
|
||||||
|
// Elem typeOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type ChanType struct {
|
||||||
|
// Tag itag // chanType
|
||||||
|
// Dir uint64 // 1 RecvOnly; 2 SendOnly; 3 SendRecv
|
||||||
|
// Elem typeOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type MapType struct {
|
||||||
|
// Tag itag // mapType
|
||||||
|
// Key typeOff
|
||||||
|
// Elem typeOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type FuncType struct {
|
||||||
|
// Tag itag // signatureType
|
||||||
|
// PkgPath stringOff
|
||||||
|
// Signature Signature
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type StructType struct {
|
||||||
|
// Tag itag // structType
|
||||||
|
// PkgPath stringOff
|
||||||
|
// Fields []struct {
|
||||||
|
// Pos Pos
|
||||||
|
// Name stringOff
|
||||||
|
// Type typeOff
|
||||||
|
// Embedded bool
|
||||||
|
// Note stringOff
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type InterfaceType struct {
|
||||||
|
// Tag itag // interfaceType
|
||||||
|
// PkgPath stringOff
|
||||||
|
// Embeddeds []struct {
|
||||||
|
// Pos Pos
|
||||||
|
// Type typeOff
|
||||||
|
// }
|
||||||
|
// Methods []struct {
|
||||||
|
// Pos Pos
|
||||||
|
// Name stringOff
|
||||||
|
// Signature Signature
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Reference to a type param declaration
|
||||||
|
// type TypeParamType struct {
|
||||||
|
// Tag itag // typeParamType
|
||||||
|
// Name stringOff
|
||||||
|
// PkgPath stringOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Instantiation of a generic type (like List[T2] or List[int])
|
||||||
|
// type InstanceType struct {
|
||||||
|
// Tag itag // instanceType
|
||||||
|
// Pos pos
|
||||||
|
// TypeArgs []typeOff
|
||||||
|
// BaseType typeOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type UnionType struct {
|
||||||
|
// Tag itag // interfaceType
|
||||||
|
// Terms []struct {
|
||||||
|
// tilde bool
|
||||||
|
// Type typeOff
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// type Signature struct {
|
||||||
|
// Params []Param
|
||||||
|
// Results []Param
|
||||||
|
// Variadic bool // omitted if Results is empty
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type Param struct {
|
||||||
|
// Pos Pos
|
||||||
|
// Name stringOff
|
||||||
|
// Type typOff
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Pos encodes a file:line:column triple, incorporating a simple delta
|
||||||
|
// encoding scheme within a data object. See exportWriter.pos for
|
||||||
|
// details.
|
||||||
|
|
||||||
package gcimporter
|
package gcimporter
|
||||||
|
|
||||||
@ -23,8 +241,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/go/types/objectpath"
|
"golang.org/x/tools/go/types/objectpath"
|
||||||
"golang.org/x/tools/internal/tokeninternal"
|
"golang.org/x/tools/internal/aliases"
|
||||||
"golang.org/x/tools/internal/typeparams"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IExportShallow encodes "shallow" export data for the specified package.
|
// IExportShallow encodes "shallow" export data for the specified package.
|
||||||
@ -223,7 +440,7 @@ func (p *iexporter) encodeFile(w *intWriter, file *token.File, needed []uint64)
|
|||||||
// Sort the set of needed offsets. Duplicates are harmless.
|
// Sort the set of needed offsets. Duplicates are harmless.
|
||||||
sort.Slice(needed, func(i, j int) bool { return needed[i] < needed[j] })
|
sort.Slice(needed, func(i, j int) bool { return needed[i] < needed[j] })
|
||||||
|
|
||||||
lines := tokeninternal.GetLines(file) // byte offset of each line start
|
lines := file.Lines() // byte offset of each line start
|
||||||
w.uint64(uint64(len(lines)))
|
w.uint64(uint64(len(lines)))
|
||||||
|
|
||||||
// Rather than record the entire array of line start offsets,
|
// Rather than record the entire array of line start offsets,
|
||||||
@ -464,7 +681,7 @@ func (p *iexporter) doDecl(obj types.Object) {
|
|||||||
|
|
||||||
switch obj := obj.(type) {
|
switch obj := obj.(type) {
|
||||||
case *types.Var:
|
case *types.Var:
|
||||||
w.tag('V')
|
w.tag(varTag)
|
||||||
w.pos(obj.Pos())
|
w.pos(obj.Pos())
|
||||||
w.typ(obj.Type(), obj.Pkg())
|
w.typ(obj.Type(), obj.Pkg())
|
||||||
|
|
||||||
@ -481,10 +698,10 @@ func (p *iexporter) doDecl(obj types.Object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function.
|
// Function.
|
||||||
if typeparams.ForSignature(sig).Len() == 0 {
|
if sig.TypeParams().Len() == 0 {
|
||||||
w.tag('F')
|
w.tag(funcTag)
|
||||||
} else {
|
} else {
|
||||||
w.tag('G')
|
w.tag(genericFuncTag)
|
||||||
}
|
}
|
||||||
w.pos(obj.Pos())
|
w.pos(obj.Pos())
|
||||||
// The tparam list of the function type is the declaration of the type
|
// The tparam list of the function type is the declaration of the type
|
||||||
@ -494,27 +711,27 @@ func (p *iexporter) doDecl(obj types.Object) {
|
|||||||
//
|
//
|
||||||
// While importing the type parameters, tparamList computes and records
|
// While importing the type parameters, tparamList computes and records
|
||||||
// their export name, so that it can be later used when writing the index.
|
// their export name, so that it can be later used when writing the index.
|
||||||
if tparams := typeparams.ForSignature(sig); tparams.Len() > 0 {
|
if tparams := sig.TypeParams(); tparams.Len() > 0 {
|
||||||
w.tparamList(obj.Name(), tparams, obj.Pkg())
|
w.tparamList(obj.Name(), tparams, obj.Pkg())
|
||||||
}
|
}
|
||||||
w.signature(sig)
|
w.signature(sig)
|
||||||
|
|
||||||
case *types.Const:
|
case *types.Const:
|
||||||
w.tag('C')
|
w.tag(constTag)
|
||||||
w.pos(obj.Pos())
|
w.pos(obj.Pos())
|
||||||
w.value(obj.Type(), obj.Val())
|
w.value(obj.Type(), obj.Val())
|
||||||
|
|
||||||
case *types.TypeName:
|
case *types.TypeName:
|
||||||
t := obj.Type()
|
t := obj.Type()
|
||||||
|
|
||||||
if tparam, ok := t.(*typeparams.TypeParam); ok {
|
if tparam, ok := types.Unalias(t).(*types.TypeParam); ok {
|
||||||
w.tag('P')
|
w.tag(typeParamTag)
|
||||||
w.pos(obj.Pos())
|
w.pos(obj.Pos())
|
||||||
constraint := tparam.Constraint()
|
constraint := tparam.Constraint()
|
||||||
if p.version >= iexportVersionGo1_18 {
|
if p.version >= iexportVersionGo1_18 {
|
||||||
implicit := false
|
implicit := false
|
||||||
if iface, _ := constraint.(*types.Interface); iface != nil {
|
if iface, _ := types.Unalias(constraint).(*types.Interface); iface != nil {
|
||||||
implicit = typeparams.IsImplicit(iface)
|
implicit = iface.IsImplicit()
|
||||||
}
|
}
|
||||||
w.bool(implicit)
|
w.bool(implicit)
|
||||||
}
|
}
|
||||||
@ -523,8 +740,26 @@ func (p *iexporter) doDecl(obj types.Object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if obj.IsAlias() {
|
if obj.IsAlias() {
|
||||||
w.tag('A')
|
alias, materialized := t.(*types.Alias) // may fail when aliases are not enabled
|
||||||
|
|
||||||
|
var tparams *types.TypeParamList
|
||||||
|
if materialized {
|
||||||
|
tparams = aliases.TypeParams(alias)
|
||||||
|
}
|
||||||
|
if tparams.Len() == 0 {
|
||||||
|
w.tag(aliasTag)
|
||||||
|
} else {
|
||||||
|
w.tag(genericAliasTag)
|
||||||
|
}
|
||||||
w.pos(obj.Pos())
|
w.pos(obj.Pos())
|
||||||
|
if tparams.Len() > 0 {
|
||||||
|
w.tparamList(obj.Name(), tparams, obj.Pkg())
|
||||||
|
}
|
||||||
|
if materialized {
|
||||||
|
// Preserve materialized aliases,
|
||||||
|
// even of non-exported types.
|
||||||
|
t = aliases.Rhs(alias)
|
||||||
|
}
|
||||||
w.typ(t, obj.Pkg())
|
w.typ(t, obj.Pkg())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -535,20 +770,20 @@ func (p *iexporter) doDecl(obj types.Object) {
|
|||||||
panic(internalErrorf("%s is not a defined type", t))
|
panic(internalErrorf("%s is not a defined type", t))
|
||||||
}
|
}
|
||||||
|
|
||||||
if typeparams.ForNamed(named).Len() == 0 {
|
if named.TypeParams().Len() == 0 {
|
||||||
w.tag('T')
|
w.tag(typeTag)
|
||||||
} else {
|
} else {
|
||||||
w.tag('U')
|
w.tag(genericTypeTag)
|
||||||
}
|
}
|
||||||
w.pos(obj.Pos())
|
w.pos(obj.Pos())
|
||||||
|
|
||||||
if typeparams.ForNamed(named).Len() > 0 {
|
if named.TypeParams().Len() > 0 {
|
||||||
// While importing the type parameters, tparamList computes and records
|
// While importing the type parameters, tparamList computes and records
|
||||||
// their export name, so that it can be later used when writing the index.
|
// their export name, so that it can be later used when writing the index.
|
||||||
w.tparamList(obj.Name(), typeparams.ForNamed(named), obj.Pkg())
|
w.tparamList(obj.Name(), named.TypeParams(), obj.Pkg())
|
||||||
}
|
}
|
||||||
|
|
||||||
underlying := obj.Type().Underlying()
|
underlying := named.Underlying()
|
||||||
w.typ(underlying, obj.Pkg())
|
w.typ(underlying, obj.Pkg())
|
||||||
|
|
||||||
if types.IsInterface(t) {
|
if types.IsInterface(t) {
|
||||||
@ -565,7 +800,7 @@ func (p *iexporter) doDecl(obj types.Object) {
|
|||||||
|
|
||||||
// Receiver type parameters are type arguments of the receiver type, so
|
// Receiver type parameters are type arguments of the receiver type, so
|
||||||
// their name must be qualified before exporting recv.
|
// their name must be qualified before exporting recv.
|
||||||
if rparams := typeparams.RecvTypeParams(sig); rparams.Len() > 0 {
|
if rparams := sig.RecvTypeParams(); rparams.Len() > 0 {
|
||||||
prefix := obj.Name() + "." + m.Name()
|
prefix := obj.Name() + "." + m.Name()
|
||||||
for i := 0; i < rparams.Len(); i++ {
|
for i := 0; i < rparams.Len(); i++ {
|
||||||
rparam := rparams.At(i)
|
rparam := rparams.At(i)
|
||||||
@ -739,20 +974,31 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
switch t := t.(type) {
|
switch t := t.(type) {
|
||||||
|
case *types.Alias:
|
||||||
|
if targs := aliases.TypeArgs(t); targs.Len() > 0 {
|
||||||
|
w.startType(instanceType)
|
||||||
|
w.pos(t.Obj().Pos())
|
||||||
|
w.typeList(targs, pkg)
|
||||||
|
w.typ(aliases.Origin(t), pkg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.startType(aliasType)
|
||||||
|
w.qualifiedType(t.Obj())
|
||||||
|
|
||||||
case *types.Named:
|
case *types.Named:
|
||||||
if targs := typeparams.NamedTypeArgs(t); targs.Len() > 0 {
|
if targs := t.TypeArgs(); targs.Len() > 0 {
|
||||||
w.startType(instanceType)
|
w.startType(instanceType)
|
||||||
// TODO(rfindley): investigate if this position is correct, and if it
|
// TODO(rfindley): investigate if this position is correct, and if it
|
||||||
// matters.
|
// matters.
|
||||||
w.pos(t.Obj().Pos())
|
w.pos(t.Obj().Pos())
|
||||||
w.typeList(targs, pkg)
|
w.typeList(targs, pkg)
|
||||||
w.typ(typeparams.NamedTypeOrigin(t), pkg)
|
w.typ(t.Origin(), pkg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.startType(definedType)
|
w.startType(definedType)
|
||||||
w.qualifiedType(t.Obj())
|
w.qualifiedType(t.Obj())
|
||||||
|
|
||||||
case *typeparams.TypeParam:
|
case *types.TypeParam:
|
||||||
w.startType(typeParamType)
|
w.startType(typeParamType)
|
||||||
w.qualifiedType(t.Obj())
|
w.qualifiedType(t.Obj())
|
||||||
|
|
||||||
@ -844,7 +1090,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
|||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
ft := t.EmbeddedType(i)
|
ft := t.EmbeddedType(i)
|
||||||
tPkg := pkg
|
tPkg := pkg
|
||||||
if named, _ := ft.(*types.Named); named != nil {
|
if named, _ := types.Unalias(ft).(*types.Named); named != nil {
|
||||||
w.pos(named.Obj().Pos())
|
w.pos(named.Obj().Pos())
|
||||||
} else {
|
} else {
|
||||||
w.pos(token.NoPos)
|
w.pos(token.NoPos)
|
||||||
@ -868,7 +1114,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
|||||||
w.signature(sig)
|
w.signature(sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *typeparams.Union:
|
case *types.Union:
|
||||||
w.startType(unionType)
|
w.startType(unionType)
|
||||||
nt := t.Len()
|
nt := t.Len()
|
||||||
w.uint64(uint64(nt))
|
w.uint64(uint64(nt))
|
||||||
@ -948,14 +1194,14 @@ func (w *exportWriter) signature(sig *types.Signature) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *exportWriter) typeList(ts *typeparams.TypeList, pkg *types.Package) {
|
func (w *exportWriter) typeList(ts *types.TypeList, pkg *types.Package) {
|
||||||
w.uint64(uint64(ts.Len()))
|
w.uint64(uint64(ts.Len()))
|
||||||
for i := 0; i < ts.Len(); i++ {
|
for i := 0; i < ts.Len(); i++ {
|
||||||
w.typ(ts.At(i), pkg)
|
w.typ(ts.At(i), pkg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *exportWriter) tparamList(prefix string, list *typeparams.TypeParamList, pkg *types.Package) {
|
func (w *exportWriter) tparamList(prefix string, list *types.TypeParamList, pkg *types.Package) {
|
||||||
ll := uint64(list.Len())
|
ll := uint64(list.Len())
|
||||||
w.uint64(ll)
|
w.uint64(ll)
|
||||||
for i := 0; i < list.Len(); i++ {
|
for i := 0; i < list.Len(); i++ {
|
||||||
@ -973,7 +1219,7 @@ const blankMarker = "$"
|
|||||||
// differs from its actual object name: it is prefixed with a qualifier, and
|
// differs from its actual object name: it is prefixed with a qualifier, and
|
||||||
// blank type parameter names are disambiguated by their index in the type
|
// blank type parameter names are disambiguated by their index in the type
|
||||||
// parameter list.
|
// parameter list.
|
||||||
func tparamExportName(prefix string, tparam *typeparams.TypeParam) string {
|
func tparamExportName(prefix string, tparam *types.TypeParam) string {
|
||||||
assert(prefix != "")
|
assert(prefix != "")
|
||||||
name := tparam.Obj().Name()
|
name := tparam.Obj().Name()
|
||||||
if name == "_" {
|
if name == "_" {
|
||||||
|
118
vendor/golang.org/x/tools/internal/gcimporter/iimport.go
generated
vendored
118
vendor/golang.org/x/tools/internal/gcimporter/iimport.go
generated
vendored
@ -3,7 +3,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Indexed package import.
|
// Indexed package import.
|
||||||
// See cmd/compile/internal/gc/iexport.go for the export data format.
|
// See iexport.go for the export data format.
|
||||||
|
|
||||||
// This file is a copy of $GOROOT/src/go/internal/gcimporter/iimport.go.
|
// This file is a copy of $GOROOT/src/go/internal/gcimporter/iimport.go.
|
||||||
|
|
||||||
@ -22,7 +22,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/go/types/objectpath"
|
"golang.org/x/tools/go/types/objectpath"
|
||||||
"golang.org/x/tools/internal/typeparams"
|
"golang.org/x/tools/internal/aliases"
|
||||||
|
"golang.org/x/tools/internal/typesinternal"
|
||||||
)
|
)
|
||||||
|
|
||||||
type intReader struct {
|
type intReader struct {
|
||||||
@ -52,6 +53,7 @@ const (
|
|||||||
iexportVersionPosCol = 1
|
iexportVersionPosCol = 1
|
||||||
iexportVersionGo1_18 = 2
|
iexportVersionGo1_18 = 2
|
||||||
iexportVersionGenerics = 2
|
iexportVersionGenerics = 2
|
||||||
|
iexportVersion = iexportVersionGenerics
|
||||||
|
|
||||||
iexportVersionCurrent = 2
|
iexportVersionCurrent = 2
|
||||||
)
|
)
|
||||||
@ -79,6 +81,20 @@ const (
|
|||||||
typeParamType
|
typeParamType
|
||||||
instanceType
|
instanceType
|
||||||
unionType
|
unionType
|
||||||
|
aliasType
|
||||||
|
)
|
||||||
|
|
||||||
|
// Object tags
|
||||||
|
const (
|
||||||
|
varTag = 'V'
|
||||||
|
funcTag = 'F'
|
||||||
|
genericFuncTag = 'G'
|
||||||
|
constTag = 'C'
|
||||||
|
aliasTag = 'A'
|
||||||
|
genericAliasTag = 'B'
|
||||||
|
typeParamTag = 'P'
|
||||||
|
typeTag = 'T'
|
||||||
|
genericTypeTag = 'U'
|
||||||
)
|
)
|
||||||
|
|
||||||
// IImportData imports a package from the serialized package data
|
// IImportData imports a package from the serialized package data
|
||||||
@ -195,6 +211,7 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte
|
|||||||
p := iimporter{
|
p := iimporter{
|
||||||
version: int(version),
|
version: int(version),
|
||||||
ipath: path,
|
ipath: path,
|
||||||
|
aliases: aliases.Enabled(),
|
||||||
shallow: shallow,
|
shallow: shallow,
|
||||||
reportf: reportf,
|
reportf: reportf,
|
||||||
|
|
||||||
@ -225,6 +242,7 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte
|
|||||||
|
|
||||||
// Gather the relevant packages from the manifest.
|
// Gather the relevant packages from the manifest.
|
||||||
items := make([]GetPackagesItem, r.uint64())
|
items := make([]GetPackagesItem, r.uint64())
|
||||||
|
uniquePkgPaths := make(map[string]bool)
|
||||||
for i := range items {
|
for i := range items {
|
||||||
pkgPathOff := r.uint64()
|
pkgPathOff := r.uint64()
|
||||||
pkgPath := p.stringAt(pkgPathOff)
|
pkgPath := p.stringAt(pkgPathOff)
|
||||||
@ -249,6 +267,12 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte
|
|||||||
}
|
}
|
||||||
|
|
||||||
items[i].nameIndex = nameIndex
|
items[i].nameIndex = nameIndex
|
||||||
|
|
||||||
|
uniquePkgPaths[pkgPath] = true
|
||||||
|
}
|
||||||
|
// Debugging #63822; hypothesis: there are duplicate PkgPaths.
|
||||||
|
if len(uniquePkgPaths) != len(items) {
|
||||||
|
reportf("found duplicate PkgPaths while reading export data manifest: %v", items)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request packages all at once from the client,
|
// Request packages all at once from the client,
|
||||||
@ -316,12 +340,12 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetConstraint can't be called if the constraint type is not yet complete.
|
// SetConstraint can't be called if the constraint type is not yet complete.
|
||||||
// When type params are created in the 'P' case of (*importReader).obj(),
|
// When type params are created in the typeParamTag case of (*importReader).obj(),
|
||||||
// the associated constraint type may not be complete due to recursion.
|
// the associated constraint type may not be complete due to recursion.
|
||||||
// Therefore, we defer calling SetConstraint there, and call it here instead
|
// Therefore, we defer calling SetConstraint there, and call it here instead
|
||||||
// after all types are complete.
|
// after all types are complete.
|
||||||
for _, d := range p.later {
|
for _, d := range p.later {
|
||||||
typeparams.SetTypeParamConstraint(d.t, d.constraint)
|
d.t.SetConstraint(d.constraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, typ := range p.interfaceList {
|
for _, typ := range p.interfaceList {
|
||||||
@ -339,7 +363,7 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte
|
|||||||
}
|
}
|
||||||
|
|
||||||
type setConstraintArgs struct {
|
type setConstraintArgs struct {
|
||||||
t *typeparams.TypeParam
|
t *types.TypeParam
|
||||||
constraint types.Type
|
constraint types.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +371,7 @@ type iimporter struct {
|
|||||||
version int
|
version int
|
||||||
ipath string
|
ipath string
|
||||||
|
|
||||||
|
aliases bool
|
||||||
shallow bool
|
shallow bool
|
||||||
reportf ReportFunc // if non-nil, used to report bugs
|
reportf ReportFunc // if non-nil, used to report bugs
|
||||||
|
|
||||||
@ -516,7 +541,7 @@ func canReuse(def *types.Named, rhs types.Type) bool {
|
|||||||
if def == nil {
|
if def == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
iface, _ := rhs.(*types.Interface)
|
iface, _ := types.Unalias(rhs).(*types.Interface)
|
||||||
if iface == nil {
|
if iface == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -538,25 +563,29 @@ func (r *importReader) obj(name string) {
|
|||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
|
|
||||||
switch tag {
|
switch tag {
|
||||||
case 'A':
|
case aliasTag, genericAliasTag:
|
||||||
|
var tparams []*types.TypeParam
|
||||||
|
if tag == genericAliasTag {
|
||||||
|
tparams = r.tparamList()
|
||||||
|
}
|
||||||
typ := r.typ()
|
typ := r.typ()
|
||||||
|
obj := aliases.NewAlias(r.p.aliases, pos, r.currPkg, name, typ, tparams)
|
||||||
|
r.declare(obj)
|
||||||
|
|
||||||
r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
|
case constTag:
|
||||||
|
|
||||||
case 'C':
|
|
||||||
typ, val := r.value()
|
typ, val := r.value()
|
||||||
|
|
||||||
r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
|
r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
|
||||||
|
|
||||||
case 'F', 'G':
|
case funcTag, genericFuncTag:
|
||||||
var tparams []*typeparams.TypeParam
|
var tparams []*types.TypeParam
|
||||||
if tag == 'G' {
|
if tag == genericFuncTag {
|
||||||
tparams = r.tparamList()
|
tparams = r.tparamList()
|
||||||
}
|
}
|
||||||
sig := r.signature(nil, nil, tparams)
|
sig := r.signature(nil, nil, tparams)
|
||||||
r.declare(types.NewFunc(pos, r.currPkg, name, sig))
|
r.declare(types.NewFunc(pos, r.currPkg, name, sig))
|
||||||
|
|
||||||
case 'T', 'U':
|
case typeTag, genericTypeTag:
|
||||||
// Types can be recursive. We need to setup a stub
|
// Types can be recursive. We need to setup a stub
|
||||||
// declaration before recursing.
|
// declaration before recursing.
|
||||||
obj := types.NewTypeName(pos, r.currPkg, name, nil)
|
obj := types.NewTypeName(pos, r.currPkg, name, nil)
|
||||||
@ -564,9 +593,9 @@ func (r *importReader) obj(name string) {
|
|||||||
// Declare obj before calling r.tparamList, so the new type name is recognized
|
// Declare obj before calling r.tparamList, so the new type name is recognized
|
||||||
// if used in the constraint of one of its own typeparams (see #48280).
|
// if used in the constraint of one of its own typeparams (see #48280).
|
||||||
r.declare(obj)
|
r.declare(obj)
|
||||||
if tag == 'U' {
|
if tag == genericTypeTag {
|
||||||
tparams := r.tparamList()
|
tparams := r.tparamList()
|
||||||
typeparams.SetForNamed(named, tparams)
|
named.SetTypeParams(tparams)
|
||||||
}
|
}
|
||||||
|
|
||||||
underlying := r.p.typAt(r.uint64(), named).Underlying()
|
underlying := r.p.typAt(r.uint64(), named).Underlying()
|
||||||
@ -581,14 +610,13 @@ func (r *importReader) obj(name string) {
|
|||||||
// If the receiver has any targs, set those as the
|
// If the receiver has any targs, set those as the
|
||||||
// rparams of the method (since those are the
|
// rparams of the method (since those are the
|
||||||
// typeparams being used in the method sig/body).
|
// typeparams being used in the method sig/body).
|
||||||
base := baseType(recv.Type())
|
_, recvNamed := typesinternal.ReceiverNamed(recv)
|
||||||
assert(base != nil)
|
targs := recvNamed.TypeArgs()
|
||||||
targs := typeparams.NamedTypeArgs(base)
|
var rparams []*types.TypeParam
|
||||||
var rparams []*typeparams.TypeParam
|
|
||||||
if targs.Len() > 0 {
|
if targs.Len() > 0 {
|
||||||
rparams = make([]*typeparams.TypeParam, targs.Len())
|
rparams = make([]*types.TypeParam, targs.Len())
|
||||||
for i := range rparams {
|
for i := range rparams {
|
||||||
rparams[i] = targs.At(i).(*typeparams.TypeParam)
|
rparams[i] = types.Unalias(targs.At(i)).(*types.TypeParam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msig := r.signature(recv, rparams, nil)
|
msig := r.signature(recv, rparams, nil)
|
||||||
@ -597,7 +625,7 @@ func (r *importReader) obj(name string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'P':
|
case typeParamTag:
|
||||||
// We need to "declare" a typeparam in order to have a name that
|
// We need to "declare" a typeparam in order to have a name that
|
||||||
// can be referenced recursively (if needed) in the type param's
|
// can be referenced recursively (if needed) in the type param's
|
||||||
// bound.
|
// bound.
|
||||||
@ -606,7 +634,7 @@ func (r *importReader) obj(name string) {
|
|||||||
}
|
}
|
||||||
name0 := tparamName(name)
|
name0 := tparamName(name)
|
||||||
tn := types.NewTypeName(pos, r.currPkg, name0, nil)
|
tn := types.NewTypeName(pos, r.currPkg, name0, nil)
|
||||||
t := typeparams.NewTypeParam(tn, nil)
|
t := types.NewTypeParam(tn, nil)
|
||||||
|
|
||||||
// To handle recursive references to the typeparam within its
|
// To handle recursive references to the typeparam within its
|
||||||
// bound, save the partial type in tparamIndex before reading the bounds.
|
// bound, save the partial type in tparamIndex before reading the bounds.
|
||||||
@ -618,11 +646,11 @@ func (r *importReader) obj(name string) {
|
|||||||
}
|
}
|
||||||
constraint := r.typ()
|
constraint := r.typ()
|
||||||
if implicit {
|
if implicit {
|
||||||
iface, _ := constraint.(*types.Interface)
|
iface, _ := types.Unalias(constraint).(*types.Interface)
|
||||||
if iface == nil {
|
if iface == nil {
|
||||||
errorf("non-interface constraint marked implicit")
|
errorf("non-interface constraint marked implicit")
|
||||||
}
|
}
|
||||||
typeparams.MarkImplicit(iface)
|
iface.MarkImplicit()
|
||||||
}
|
}
|
||||||
// The constraint type may not be complete, if we
|
// The constraint type may not be complete, if we
|
||||||
// are in the middle of a type recursion involving type
|
// are in the middle of a type recursion involving type
|
||||||
@ -630,7 +658,7 @@ func (r *importReader) obj(name string) {
|
|||||||
// completely set up all types in ImportData.
|
// completely set up all types in ImportData.
|
||||||
r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
|
r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
|
||||||
|
|
||||||
case 'V':
|
case varTag:
|
||||||
typ := r.typ()
|
typ := r.typ()
|
||||||
|
|
||||||
r.declare(types.NewVar(pos, r.currPkg, name, typ))
|
r.declare(types.NewVar(pos, r.currPkg, name, typ))
|
||||||
@ -825,7 +853,7 @@ func (r *importReader) typ() types.Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isInterface(t types.Type) bool {
|
func isInterface(t types.Type) bool {
|
||||||
_, ok := t.(*types.Interface)
|
_, ok := types.Unalias(t).(*types.Interface)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -835,7 +863,7 @@ func (r *importReader) string() string { return r.p.stringAt(r.uint64()) }
|
|||||||
func (r *importReader) doType(base *types.Named) (res types.Type) {
|
func (r *importReader) doType(base *types.Named) (res types.Type) {
|
||||||
k := r.kind()
|
k := r.kind()
|
||||||
if debug {
|
if debug {
|
||||||
r.p.trace("importing type %d (base: %s)", k, base)
|
r.p.trace("importing type %d (base: %v)", k, base)
|
||||||
r.p.indent++
|
r.p.indent++
|
||||||
defer func() {
|
defer func() {
|
||||||
r.p.indent--
|
r.p.indent--
|
||||||
@ -847,7 +875,7 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
|||||||
errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
|
errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case definedType:
|
case aliasType, definedType:
|
||||||
pkg, name := r.qualifiedIdent()
|
pkg, name := r.qualifiedIdent()
|
||||||
r.p.doDecl(pkg, name)
|
r.p.doDecl(pkg, name)
|
||||||
return pkg.Scope().Lookup(name).(*types.TypeName).Type()
|
return pkg.Scope().Lookup(name).(*types.TypeName).Type()
|
||||||
@ -932,7 +960,7 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
|||||||
methods[i] = method
|
methods[i] = method
|
||||||
}
|
}
|
||||||
|
|
||||||
typ := newInterface(methods, embeddeds)
|
typ := types.NewInterfaceType(methods, embeddeds)
|
||||||
r.p.interfaceList = append(r.p.interfaceList, typ)
|
r.p.interfaceList = append(r.p.interfaceList, typ)
|
||||||
return typ
|
return typ
|
||||||
|
|
||||||
@ -966,7 +994,7 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
|||||||
// The imported instantiated type doesn't include any methods, so
|
// The imported instantiated type doesn't include any methods, so
|
||||||
// we must always use the methods of the base (orig) type.
|
// we must always use the methods of the base (orig) type.
|
||||||
// TODO provide a non-nil *Environment
|
// TODO provide a non-nil *Environment
|
||||||
t, _ := typeparams.Instantiate(nil, baseType, targs, false)
|
t, _ := types.Instantiate(nil, baseType, targs, false)
|
||||||
|
|
||||||
// Workaround for golang/go#61561. See the doc for instanceList for details.
|
// Workaround for golang/go#61561. See the doc for instanceList for details.
|
||||||
r.p.instanceList = append(r.p.instanceList, t)
|
r.p.instanceList = append(r.p.instanceList, t)
|
||||||
@ -976,11 +1004,11 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
|||||||
if r.p.version < iexportVersionGenerics {
|
if r.p.version < iexportVersionGenerics {
|
||||||
errorf("unexpected instantiation type")
|
errorf("unexpected instantiation type")
|
||||||
}
|
}
|
||||||
terms := make([]*typeparams.Term, r.uint64())
|
terms := make([]*types.Term, r.uint64())
|
||||||
for i := range terms {
|
for i := range terms {
|
||||||
terms[i] = typeparams.NewTerm(r.bool(), r.typ())
|
terms[i] = types.NewTerm(r.bool(), r.typ())
|
||||||
}
|
}
|
||||||
return typeparams.NewUnion(terms)
|
return types.NewUnion(terms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1008,23 +1036,23 @@ func (r *importReader) objectPathObject() types.Object {
|
|||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *importReader) signature(recv *types.Var, rparams []*typeparams.TypeParam, tparams []*typeparams.TypeParam) *types.Signature {
|
func (r *importReader) signature(recv *types.Var, rparams []*types.TypeParam, tparams []*types.TypeParam) *types.Signature {
|
||||||
params := r.paramList()
|
params := r.paramList()
|
||||||
results := r.paramList()
|
results := r.paramList()
|
||||||
variadic := params.Len() > 0 && r.bool()
|
variadic := params.Len() > 0 && r.bool()
|
||||||
return typeparams.NewSignatureType(recv, rparams, tparams, params, results, variadic)
|
return types.NewSignatureType(recv, rparams, tparams, params, results, variadic)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *importReader) tparamList() []*typeparams.TypeParam {
|
func (r *importReader) tparamList() []*types.TypeParam {
|
||||||
n := r.uint64()
|
n := r.uint64()
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
xs := make([]*typeparams.TypeParam, n)
|
xs := make([]*types.TypeParam, n)
|
||||||
for i := range xs {
|
for i := range xs {
|
||||||
// Note: the standard library importer is tolerant of nil types here,
|
// Note: the standard library importer is tolerant of nil types here,
|
||||||
// though would panic in SetTypeParams.
|
// though would panic in SetTypeParams.
|
||||||
xs[i] = r.typ().(*typeparams.TypeParam)
|
xs[i] = types.Unalias(r.typ()).(*types.TypeParam)
|
||||||
}
|
}
|
||||||
return xs
|
return xs
|
||||||
}
|
}
|
||||||
@ -1071,13 +1099,3 @@ func (r *importReader) byte() byte {
|
|||||||
}
|
}
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
func baseType(typ types.Type) *types.Named {
|
|
||||||
// pointer receivers are never types.Named types
|
|
||||||
if p, _ := typ.(*types.Pointer); p != nil {
|
|
||||||
typ = p.Elem()
|
|
||||||
}
|
|
||||||
// receiver base types are always (possibly generic) types.Named types
|
|
||||||
n, _ := typ.(*types.Named)
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
22
vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go
generated
vendored
22
vendor/golang.org/x/tools/internal/gcimporter/newInterface10.go
generated
vendored
@ -1,22 +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.
|
|
||||||
|
|
||||||
//go:build !go1.11
|
|
||||||
// +build !go1.11
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
import "go/types"
|
|
||||||
|
|
||||||
func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface {
|
|
||||||
named := make([]*types.Named, len(embeddeds))
|
|
||||||
for i, e := range embeddeds {
|
|
||||||
var ok bool
|
|
||||||
named[i], ok = e.(*types.Named)
|
|
||||||
if !ok {
|
|
||||||
panic("embedding of non-defined interfaces in interfaces is not supported before Go 1.11")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return types.NewInterface(methods, named)
|
|
||||||
}
|
|
14
vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go
generated
vendored
14
vendor/golang.org/x/tools/internal/gcimporter/newInterface11.go
generated
vendored
@ -1,14 +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.
|
|
||||||
|
|
||||||
//go:build go1.11
|
|
||||||
// +build go1.11
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
import "go/types"
|
|
||||||
|
|
||||||
func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface {
|
|
||||||
return types.NewInterfaceType(methods, embeddeds)
|
|
||||||
}
|
|
91
vendor/golang.org/x/tools/internal/gcimporter/predeclared.go
generated
vendored
Normal file
91
vendor/golang.org/x/tools/internal/gcimporter/predeclared.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gcimporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// predecl is a cache for the predeclared types in types.Universe.
|
||||||
|
//
|
||||||
|
// Cache a distinct result based on the runtime value of any.
|
||||||
|
// The pointer value of the any type varies based on GODEBUG settings.
|
||||||
|
var predeclMu sync.Mutex
|
||||||
|
var predecl map[types.Type][]types.Type
|
||||||
|
|
||||||
|
func predeclared() []types.Type {
|
||||||
|
anyt := types.Universe.Lookup("any").Type()
|
||||||
|
|
||||||
|
predeclMu.Lock()
|
||||||
|
defer predeclMu.Unlock()
|
||||||
|
|
||||||
|
if pre, ok := predecl[anyt]; ok {
|
||||||
|
return pre
|
||||||
|
}
|
||||||
|
|
||||||
|
if predecl == nil {
|
||||||
|
predecl = make(map[types.Type][]types.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
decls := []types.Type{ // basic types
|
||||||
|
types.Typ[types.Bool],
|
||||||
|
types.Typ[types.Int],
|
||||||
|
types.Typ[types.Int8],
|
||||||
|
types.Typ[types.Int16],
|
||||||
|
types.Typ[types.Int32],
|
||||||
|
types.Typ[types.Int64],
|
||||||
|
types.Typ[types.Uint],
|
||||||
|
types.Typ[types.Uint8],
|
||||||
|
types.Typ[types.Uint16],
|
||||||
|
types.Typ[types.Uint32],
|
||||||
|
types.Typ[types.Uint64],
|
||||||
|
types.Typ[types.Uintptr],
|
||||||
|
types.Typ[types.Float32],
|
||||||
|
types.Typ[types.Float64],
|
||||||
|
types.Typ[types.Complex64],
|
||||||
|
types.Typ[types.Complex128],
|
||||||
|
types.Typ[types.String],
|
||||||
|
|
||||||
|
// basic type aliases
|
||||||
|
types.Universe.Lookup("byte").Type(),
|
||||||
|
types.Universe.Lookup("rune").Type(),
|
||||||
|
|
||||||
|
// error
|
||||||
|
types.Universe.Lookup("error").Type(),
|
||||||
|
|
||||||
|
// untyped types
|
||||||
|
types.Typ[types.UntypedBool],
|
||||||
|
types.Typ[types.UntypedInt],
|
||||||
|
types.Typ[types.UntypedRune],
|
||||||
|
types.Typ[types.UntypedFloat],
|
||||||
|
types.Typ[types.UntypedComplex],
|
||||||
|
types.Typ[types.UntypedString],
|
||||||
|
types.Typ[types.UntypedNil],
|
||||||
|
|
||||||
|
// package unsafe
|
||||||
|
types.Typ[types.UnsafePointer],
|
||||||
|
|
||||||
|
// invalid type
|
||||||
|
types.Typ[types.Invalid], // only appears in packages with errors
|
||||||
|
|
||||||
|
// used internally by gc; never used by this package or in .a files
|
||||||
|
anyType{},
|
||||||
|
|
||||||
|
// comparable
|
||||||
|
types.Universe.Lookup("comparable").Type(),
|
||||||
|
|
||||||
|
// any
|
||||||
|
anyt,
|
||||||
|
}
|
||||||
|
|
||||||
|
predecl[anyt] = decls
|
||||||
|
return decls
|
||||||
|
}
|
||||||
|
|
||||||
|
type anyType struct{}
|
||||||
|
|
||||||
|
func (t anyType) Underlying() types.Type { return t }
|
||||||
|
func (t anyType) String() string { return "any" }
|
16
vendor/golang.org/x/tools/internal/gcimporter/support_go117.go
generated
vendored
16
vendor/golang.org/x/tools/internal/gcimporter/support_go117.go
generated
vendored
@ -1,16 +0,0 @@
|
|||||||
// Copyright 2021 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.18
|
|
||||||
// +build !go1.18
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
import "go/types"
|
|
||||||
|
|
||||||
const iexportVersion = iexportVersionGo1_11
|
|
||||||
|
|
||||||
func additionalPredeclared() []types.Type {
|
|
||||||
return nil
|
|
||||||
}
|
|
37
vendor/golang.org/x/tools/internal/gcimporter/support_go118.go
generated
vendored
37
vendor/golang.org/x/tools/internal/gcimporter/support_go118.go
generated
vendored
@ -1,37 +0,0 @@
|
|||||||
// Copyright 2021 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.18
|
|
||||||
// +build go1.18
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
import "go/types"
|
|
||||||
|
|
||||||
const iexportVersion = iexportVersionGenerics
|
|
||||||
|
|
||||||
// additionalPredeclared returns additional predeclared types in go.1.18.
|
|
||||||
func additionalPredeclared() []types.Type {
|
|
||||||
return []types.Type{
|
|
||||||
// comparable
|
|
||||||
types.Universe.Lookup("comparable").Type(),
|
|
||||||
|
|
||||||
// any
|
|
||||||
types.Universe.Lookup("any").Type(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See cmd/compile/internal/types.SplitVargenSuffix.
|
|
||||||
func splitVargenSuffix(name string) (base, suffix string) {
|
|
||||||
i := len(name)
|
|
||||||
for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' {
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
const dot = "·"
|
|
||||||
if i >= len(dot) && name[i-len(dot):i] == dot {
|
|
||||||
i -= len(dot)
|
|
||||||
return name[:i], name[i:]
|
|
||||||
}
|
|
||||||
return name, ""
|
|
||||||
}
|
|
10
vendor/golang.org/x/tools/internal/gcimporter/unified_no.go
generated
vendored
10
vendor/golang.org/x/tools/internal/gcimporter/unified_no.go
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
// Copyright 2022 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.18 && goexperiment.unified)
|
|
||||||
// +build !go1.18 !goexperiment.unified
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
const unifiedIR = false
|
|
10
vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go
generated
vendored
10
vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
// Copyright 2022 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.18 && goexperiment.unified
|
|
||||||
// +build go1.18,goexperiment.unified
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
const unifiedIR = true
|
|
19
vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go
generated
vendored
19
vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
// Copyright 2022 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.18
|
|
||||||
// +build !go1.18
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/token"
|
|
||||||
"go/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
|
||||||
err = fmt.Errorf("go/tools compiled with a Go version earlier than 1.18 cannot read unified IR export data")
|
|
||||||
return
|
|
||||||
}
|
|
50
vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go
generated
vendored
50
vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go
generated
vendored
@ -4,9 +4,6 @@
|
|||||||
|
|
||||||
// Derived from go/internal/gcimporter/ureader.go
|
// Derived from go/internal/gcimporter/ureader.go
|
||||||
|
|
||||||
//go:build go1.18
|
|
||||||
// +build go1.18
|
|
||||||
|
|
||||||
package gcimporter
|
package gcimporter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -16,6 +13,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/aliases"
|
||||||
"golang.org/x/tools/internal/pkgbits"
|
"golang.org/x/tools/internal/pkgbits"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,6 +26,7 @@ type pkgReader struct {
|
|||||||
|
|
||||||
ctxt *types.Context
|
ctxt *types.Context
|
||||||
imports map[string]*types.Package // previously imported packages, indexed by path
|
imports map[string]*types.Package // previously imported packages, indexed by path
|
||||||
|
aliases bool // create types.Alias nodes
|
||||||
|
|
||||||
// lazily initialized arrays corresponding to the unified IR
|
// lazily initialized arrays corresponding to the unified IR
|
||||||
// PosBase, Pkg, and Type sections, respectively.
|
// PosBase, Pkg, and Type sections, respectively.
|
||||||
@ -53,8 +52,7 @@ func (pr *pkgReader) later(fn func()) {
|
|||||||
|
|
||||||
// See cmd/compile/internal/noder.derivedInfo.
|
// See cmd/compile/internal/noder.derivedInfo.
|
||||||
type derivedInfo struct {
|
type derivedInfo struct {
|
||||||
idx pkgbits.Index
|
idx pkgbits.Index
|
||||||
needed bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// See cmd/compile/internal/noder.typeInfo.
|
// See cmd/compile/internal/noder.typeInfo.
|
||||||
@ -101,6 +99,7 @@ func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[st
|
|||||||
|
|
||||||
ctxt: ctxt,
|
ctxt: ctxt,
|
||||||
imports: imports,
|
imports: imports,
|
||||||
|
aliases: aliases.Enabled(),
|
||||||
|
|
||||||
posBases: make([]string, input.NumElems(pkgbits.RelocPosBase)),
|
posBases: make([]string, input.NumElems(pkgbits.RelocPosBase)),
|
||||||
pkgs: make([]*types.Package, input.NumElems(pkgbits.RelocPkg)),
|
pkgs: make([]*types.Package, input.NumElems(pkgbits.RelocPkg)),
|
||||||
@ -110,13 +109,17 @@ func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[st
|
|||||||
|
|
||||||
r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
|
r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
|
||||||
pkg := r.pkg()
|
pkg := r.pkg()
|
||||||
r.Bool() // has init
|
if r.Version().Has(pkgbits.HasInit) {
|
||||||
|
r.Bool()
|
||||||
|
}
|
||||||
|
|
||||||
for i, n := 0, r.Len(); i < n; i++ {
|
for i, n := 0, r.Len(); i < n; i++ {
|
||||||
// As if r.obj(), but avoiding the Scope.Lookup call,
|
// As if r.obj(), but avoiding the Scope.Lookup call,
|
||||||
// to avoid eager loading of imports.
|
// to avoid eager loading of imports.
|
||||||
r.Sync(pkgbits.SyncObject)
|
r.Sync(pkgbits.SyncObject)
|
||||||
assert(!r.Bool())
|
if r.Version().Has(pkgbits.DerivedFuncInstance) {
|
||||||
|
assert(!r.Bool())
|
||||||
|
}
|
||||||
r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
||||||
assert(r.Len() == 0)
|
assert(r.Len() == 0)
|
||||||
}
|
}
|
||||||
@ -165,7 +168,7 @@ type readerDict struct {
|
|||||||
// tparams is a slice of the constructed TypeParams for the element.
|
// tparams is a slice of the constructed TypeParams for the element.
|
||||||
tparams []*types.TypeParam
|
tparams []*types.TypeParam
|
||||||
|
|
||||||
// devived is a slice of types derived from tparams, which may be
|
// derived is a slice of types derived from tparams, which may be
|
||||||
// instantiated while reading the current element.
|
// instantiated while reading the current element.
|
||||||
derived []derivedInfo
|
derived []derivedInfo
|
||||||
derivedTypes []types.Type // lazily instantiated from derived
|
derivedTypes []types.Type // lazily instantiated from derived
|
||||||
@ -471,7 +474,9 @@ func (r *reader) param() *types.Var {
|
|||||||
func (r *reader) obj() (types.Object, []types.Type) {
|
func (r *reader) obj() (types.Object, []types.Type) {
|
||||||
r.Sync(pkgbits.SyncObject)
|
r.Sync(pkgbits.SyncObject)
|
||||||
|
|
||||||
assert(!r.Bool())
|
if r.Version().Has(pkgbits.DerivedFuncInstance) {
|
||||||
|
assert(!r.Bool())
|
||||||
|
}
|
||||||
|
|
||||||
pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj))
|
||||||
obj := pkgScope(pkg).Lookup(name)
|
obj := pkgScope(pkg).Lookup(name)
|
||||||
@ -525,8 +530,12 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
|
|||||||
|
|
||||||
case pkgbits.ObjAlias:
|
case pkgbits.ObjAlias:
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
|
var tparams []*types.TypeParam
|
||||||
|
if r.Version().Has(pkgbits.AliasTypeParamNames) {
|
||||||
|
tparams = r.typeParamNames()
|
||||||
|
}
|
||||||
typ := r.typ()
|
typ := r.typ()
|
||||||
declare(types.NewTypeName(pos, objPkg, objName, typ))
|
declare(aliases.NewAlias(r.p.aliases, pos, objPkg, objName, typ, tparams))
|
||||||
|
|
||||||
case pkgbits.ObjConst:
|
case pkgbits.ObjConst:
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
@ -553,7 +562,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
|
|||||||
// If the underlying type is an interface, we need to
|
// If the underlying type is an interface, we need to
|
||||||
// duplicate its methods so we can replace the receiver
|
// duplicate its methods so we can replace the receiver
|
||||||
// parameter's type (#49906).
|
// parameter's type (#49906).
|
||||||
if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
|
if iface, ok := types.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
|
||||||
methods := make([]*types.Func, iface.NumExplicitMethods())
|
methods := make([]*types.Func, iface.NumExplicitMethods())
|
||||||
for i := range methods {
|
for i := range methods {
|
||||||
fn := iface.ExplicitMethod(i)
|
fn := iface.ExplicitMethod(i)
|
||||||
@ -632,7 +641,10 @@ func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
|
|||||||
dict.derived = make([]derivedInfo, r.Len())
|
dict.derived = make([]derivedInfo, r.Len())
|
||||||
dict.derivedTypes = make([]types.Type, len(dict.derived))
|
dict.derivedTypes = make([]types.Type, len(dict.derived))
|
||||||
for i := range dict.derived {
|
for i := range dict.derived {
|
||||||
dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()}
|
dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.RelocType)}
|
||||||
|
if r.Version().Has(pkgbits.DerivedInfoNeeded) {
|
||||||
|
assert(!r.Bool())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pr.retireReader(r)
|
pr.retireReader(r)
|
||||||
@ -726,3 +738,17 @@ func pkgScope(pkg *types.Package) *types.Scope {
|
|||||||
}
|
}
|
||||||
return types.Universe
|
return types.Universe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See cmd/compile/internal/types.SplitVargenSuffix.
|
||||||
|
func splitVargenSuffix(name string) (base, suffix string) {
|
||||||
|
i := len(name)
|
||||||
|
for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' {
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
const dot = "·"
|
||||||
|
if i >= len(dot) && name[i-len(dot):i] == dot {
|
||||||
|
i -= len(dot)
|
||||||
|
return name[:i], name[i:]
|
||||||
|
}
|
||||||
|
return name, ""
|
||||||
|
}
|
||||||
|
173
vendor/golang.org/x/tools/internal/gocommand/invoke.go
generated
vendored
173
vendor/golang.org/x/tools/internal/gocommand/invoke.go
generated
vendored
@ -8,12 +8,14 @@ package gocommand
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -21,12 +23,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
exec "golang.org/x/sys/execabs"
|
|
||||||
|
|
||||||
"golang.org/x/tools/internal/event"
|
"golang.org/x/tools/internal/event"
|
||||||
"golang.org/x/tools/internal/event/keys"
|
"golang.org/x/tools/internal/event/keys"
|
||||||
"golang.org/x/tools/internal/event/label"
|
"golang.org/x/tools/internal/event/label"
|
||||||
"golang.org/x/tools/internal/event/tag"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// An Runner will run go command invocations and serialize
|
// An Runner will run go command invocations and serialize
|
||||||
@ -56,11 +55,14 @@ func (runner *Runner) initialize() {
|
|||||||
// 1.14: go: updating go.mod: existing contents have changed since last read
|
// 1.14: go: updating go.mod: existing contents have changed since last read
|
||||||
var modConcurrencyError = regexp.MustCompile(`go:.*go.mod.*contents have changed`)
|
var modConcurrencyError = regexp.MustCompile(`go:.*go.mod.*contents have changed`)
|
||||||
|
|
||||||
// verb is an event label for the go command verb.
|
// event keys for go command invocations
|
||||||
var verb = keys.NewString("verb", "go command verb")
|
var (
|
||||||
|
verb = keys.NewString("verb", "go command verb")
|
||||||
|
directory = keys.NewString("directory", "")
|
||||||
|
)
|
||||||
|
|
||||||
func invLabels(inv Invocation) []label.Label {
|
func invLabels(inv Invocation) []label.Label {
|
||||||
return []label.Label{verb.Of(inv.Verb), tag.Directory.Of(inv.WorkingDir)}
|
return []label.Label{verb.Of(inv.Verb), directory.Of(inv.WorkingDir)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run is a convenience wrapper around RunRaw.
|
// Run is a convenience wrapper around RunRaw.
|
||||||
@ -85,6 +87,7 @@ func (runner *Runner) RunPiped(ctx context.Context, inv Invocation, stdout, stde
|
|||||||
|
|
||||||
// RunRaw runs the invocation, serializing requests only if they fight over
|
// RunRaw runs the invocation, serializing requests only if they fight over
|
||||||
// go.mod changes.
|
// go.mod changes.
|
||||||
|
// Postcondition: both error results have same nilness.
|
||||||
func (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) {
|
func (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) {
|
||||||
ctx, done := event.Start(ctx, "gocommand.Runner.RunRaw", invLabels(inv)...)
|
ctx, done := event.Start(ctx, "gocommand.Runner.RunRaw", invLabels(inv)...)
|
||||||
defer done()
|
defer done()
|
||||||
@ -95,23 +98,24 @@ func (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer
|
|||||||
stdout, stderr, friendlyErr, err := runner.runConcurrent(ctx, inv)
|
stdout, stderr, friendlyErr, err := runner.runConcurrent(ctx, inv)
|
||||||
|
|
||||||
// If we encounter a load concurrency error, we need to retry serially.
|
// If we encounter a load concurrency error, we need to retry serially.
|
||||||
if friendlyErr == nil || !modConcurrencyError.MatchString(friendlyErr.Error()) {
|
if friendlyErr != nil && modConcurrencyError.MatchString(friendlyErr.Error()) {
|
||||||
return stdout, stderr, friendlyErr, err
|
event.Error(ctx, "Load concurrency error, will retry serially", err)
|
||||||
}
|
|
||||||
event.Error(ctx, "Load concurrency error, will retry serially", err)
|
// Run serially by calling runPiped.
|
||||||
|
stdout.Reset()
|
||||||
|
stderr.Reset()
|
||||||
|
friendlyErr, err = runner.runPiped(ctx, inv, stdout, stderr)
|
||||||
|
}
|
||||||
|
|
||||||
// Run serially by calling runPiped.
|
|
||||||
stdout.Reset()
|
|
||||||
stderr.Reset()
|
|
||||||
friendlyErr, err = runner.runPiped(ctx, inv, stdout, stderr)
|
|
||||||
return stdout, stderr, friendlyErr, err
|
return stdout, stderr, friendlyErr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Postcondition: both error results have same nilness.
|
||||||
func (runner *Runner) runConcurrent(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) {
|
func (runner *Runner) runConcurrent(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) {
|
||||||
// Wait for 1 worker to become available.
|
// Wait for 1 worker to become available.
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil, nil, nil, ctx.Err()
|
return nil, nil, ctx.Err(), ctx.Err()
|
||||||
case runner.inFlight <- struct{}{}:
|
case runner.inFlight <- struct{}{}:
|
||||||
defer func() { <-runner.inFlight }()
|
defer func() { <-runner.inFlight }()
|
||||||
}
|
}
|
||||||
@ -121,6 +125,7 @@ func (runner *Runner) runConcurrent(ctx context.Context, inv Invocation) (*bytes
|
|||||||
return stdout, stderr, friendlyErr, err
|
return stdout, stderr, friendlyErr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Postcondition: both error results have same nilness.
|
||||||
func (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stderr io.Writer) (error, error) {
|
func (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stderr io.Writer) (error, error) {
|
||||||
// Make sure the runner is always initialized.
|
// Make sure the runner is always initialized.
|
||||||
runner.initialize()
|
runner.initialize()
|
||||||
@ -129,7 +134,7 @@ func (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stde
|
|||||||
// runPiped commands.
|
// runPiped commands.
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil, ctx.Err()
|
return ctx.Err(), ctx.Err()
|
||||||
case runner.serialized <- struct{}{}:
|
case runner.serialized <- struct{}{}:
|
||||||
defer func() { <-runner.serialized }()
|
defer func() { <-runner.serialized }()
|
||||||
}
|
}
|
||||||
@ -139,7 +144,7 @@ func (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stde
|
|||||||
for i := 0; i < maxInFlight; i++ {
|
for i := 0; i < maxInFlight; i++ {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil, ctx.Err()
|
return ctx.Err(), ctx.Err()
|
||||||
case runner.inFlight <- struct{}{}:
|
case runner.inFlight <- struct{}{}:
|
||||||
// Make sure we always "return" any workers we took.
|
// Make sure we always "return" any workers we took.
|
||||||
defer func() { <-runner.inFlight }()
|
defer func() { <-runner.inFlight }()
|
||||||
@ -156,12 +161,17 @@ type Invocation struct {
|
|||||||
BuildFlags []string
|
BuildFlags []string
|
||||||
|
|
||||||
// If ModFlag is set, the go command is invoked with -mod=ModFlag.
|
// If ModFlag is set, the go command is invoked with -mod=ModFlag.
|
||||||
|
// TODO(rfindley): remove, in favor of Args.
|
||||||
ModFlag string
|
ModFlag string
|
||||||
|
|
||||||
// If ModFile is set, the go command is invoked with -modfile=ModFile.
|
// If ModFile is set, the go command is invoked with -modfile=ModFile.
|
||||||
|
// TODO(rfindley): remove, in favor of Args.
|
||||||
ModFile string
|
ModFile string
|
||||||
|
|
||||||
// If Overlay is set, the go command is invoked with -overlay=Overlay.
|
// Overlay is the name of the JSON overlay file that describes
|
||||||
|
// unsaved editor buffers; see [WriteOverlays].
|
||||||
|
// If set, the go command is invoked with -overlay=Overlay.
|
||||||
|
// TODO(rfindley): remove, in favor of Args.
|
||||||
Overlay string
|
Overlay string
|
||||||
|
|
||||||
// If CleanEnv is set, the invocation will run only with the environment
|
// If CleanEnv is set, the invocation will run only with the environment
|
||||||
@ -172,6 +182,7 @@ type Invocation struct {
|
|||||||
Logf func(format string, args ...interface{})
|
Logf func(format string, args ...interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Postcondition: both error results have same nilness.
|
||||||
func (i *Invocation) runWithFriendlyError(ctx context.Context, stdout, stderr io.Writer) (friendlyError error, rawError error) {
|
func (i *Invocation) runWithFriendlyError(ctx context.Context, stdout, stderr io.Writer) (friendlyError error, rawError error) {
|
||||||
rawError = i.run(ctx, stdout, stderr)
|
rawError = i.run(ctx, stdout, stderr)
|
||||||
if rawError != nil {
|
if rawError != nil {
|
||||||
@ -188,12 +199,14 @@ func (i *Invocation) runWithFriendlyError(ctx context.Context, stdout, stderr io
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
|
// logf logs if i.Logf is non-nil.
|
||||||
log := i.Logf
|
func (i *Invocation) logf(format string, args ...any) {
|
||||||
if log == nil {
|
if i.Logf != nil {
|
||||||
log = func(string, ...interface{}) {}
|
i.Logf(format, args...)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
|
||||||
goArgs := []string{i.Verb}
|
goArgs := []string{i.Verb}
|
||||||
|
|
||||||
appendModFile := func() {
|
appendModFile := func() {
|
||||||
@ -236,23 +249,23 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
|
|||||||
cmd.Stdout = stdout
|
cmd.Stdout = stdout
|
||||||
cmd.Stderr = stderr
|
cmd.Stderr = stderr
|
||||||
|
|
||||||
// cmd.WaitDelay was added only in go1.20 (see #50436).
|
// https://go.dev/issue/59541: don't wait forever copying stderr
|
||||||
if waitDelay := reflect.ValueOf(cmd).Elem().FieldByName("WaitDelay"); waitDelay.IsValid() {
|
// after the command has exited.
|
||||||
// https://go.dev/issue/59541: don't wait forever copying stderr
|
// After CL 484741 we copy stdout manually, so we we'll stop reading that as
|
||||||
// after the command has exited.
|
// soon as ctx is done. However, we also don't want to wait around forever
|
||||||
// After CL 484741 we copy stdout manually, so we we'll stop reading that as
|
// for stderr. Give a much-longer-than-reasonable delay and then assume that
|
||||||
// soon as ctx is done. However, we also don't want to wait around forever
|
// something has wedged in the kernel or runtime.
|
||||||
// for stderr. Give a much-longer-than-reasonable delay and then assume that
|
cmd.WaitDelay = 30 * time.Second
|
||||||
// something has wedged in the kernel or runtime.
|
|
||||||
waitDelay.Set(reflect.ValueOf(30 * time.Second))
|
|
||||||
}
|
|
||||||
|
|
||||||
// On darwin the cwd gets resolved to the real path, which breaks anything that
|
// The cwd gets resolved to the real path. On Darwin, where
|
||||||
// expects the working directory to keep the original path, including the
|
// /tmp is a symlink, this breaks anything that expects the
|
||||||
|
// working directory to keep the original path, including the
|
||||||
// go command when dealing with modules.
|
// go command when dealing with modules.
|
||||||
// The Go stdlib has a special feature where if the cwd and the PWD are the
|
//
|
||||||
// same node then it trusts the PWD, so by setting it in the env for the child
|
// os.Getwd has a special feature where if the cwd and the PWD
|
||||||
// process we fix up all the paths returned by the go command.
|
// are the same node then it trusts the PWD, so by setting it
|
||||||
|
// in the env for the child process we fix up all the paths
|
||||||
|
// returned by the go command.
|
||||||
if !i.CleanEnv {
|
if !i.CleanEnv {
|
||||||
cmd.Env = os.Environ()
|
cmd.Env = os.Environ()
|
||||||
}
|
}
|
||||||
@ -262,7 +275,12 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
|
|||||||
cmd.Dir = i.WorkingDir
|
cmd.Dir = i.WorkingDir
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func(start time.Time) { log("%s for %v", time.Since(start), cmdDebugStr(cmd)) }(time.Now())
|
debugStr := cmdDebugStr(cmd)
|
||||||
|
i.logf("starting %v", debugStr)
|
||||||
|
start := time.Now()
|
||||||
|
defer func() {
|
||||||
|
i.logf("%s for %v", time.Since(start), debugStr)
|
||||||
|
}()
|
||||||
|
|
||||||
return runCmdContext(ctx, cmd)
|
return runCmdContext(ctx, cmd)
|
||||||
}
|
}
|
||||||
@ -343,6 +361,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startTime := time.Now()
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if stdoutW != nil {
|
if stdoutW != nil {
|
||||||
// The child process has inherited the pipe file,
|
// The child process has inherited the pipe file,
|
||||||
@ -369,7 +388,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {
|
|||||||
case err := <-resChan:
|
case err := <-resChan:
|
||||||
return err
|
return err
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
HandleHangingGoCommand(cmd.Process)
|
HandleHangingGoCommand(startTime, cmd)
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -403,7 +422,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {
|
|||||||
return <-resChan
|
return <-resChan
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleHangingGoCommand(proc *os.Process) {
|
func HandleHangingGoCommand(start time.Time, cmd *exec.Cmd) {
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "linux", "darwin", "freebsd", "netbsd":
|
case "linux", "darwin", "freebsd", "netbsd":
|
||||||
fmt.Fprintln(os.Stderr, `DETECTED A HANGING GO COMMAND
|
fmt.Fprintln(os.Stderr, `DETECTED A HANGING GO COMMAND
|
||||||
@ -436,7 +455,7 @@ See golang/go#54461 for more details.`)
|
|||||||
panic(fmt.Sprintf("running %s: %v", listFiles, err))
|
panic(fmt.Sprintf("running %s: %v", listFiles, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("detected hanging go command (pid %d): see golang/go#54461 for more details", proc.Pid))
|
panic(fmt.Sprintf("detected hanging go command (golang/go#54461); waited %s\n\tcommand:%s\n\tpid:%d", time.Since(start), cmd, cmd.Process.Pid))
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdDebugStr(cmd *exec.Cmd) string {
|
func cmdDebugStr(cmd *exec.Cmd) string {
|
||||||
@ -460,3 +479,73 @@ func cmdDebugStr(cmd *exec.Cmd) string {
|
|||||||
}
|
}
|
||||||
return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], strings.Join(args, " "))
|
return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], strings.Join(args, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteOverlays writes each value in the overlay (see the Overlay
|
||||||
|
// field of go/packages.Config) to a temporary file and returns the name
|
||||||
|
// of a JSON file describing the mapping that is suitable for the "go
|
||||||
|
// list -overlay" flag.
|
||||||
|
//
|
||||||
|
// On success, the caller must call the cleanup function exactly once
|
||||||
|
// when the files are no longer needed.
|
||||||
|
func WriteOverlays(overlay map[string][]byte) (filename string, cleanup func(), err error) {
|
||||||
|
// Do nothing if there are no overlays in the config.
|
||||||
|
if len(overlay) == 0 {
|
||||||
|
return "", func() {}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dir, err := os.MkdirTemp("", "gocommand-*")
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The caller must clean up this directory,
|
||||||
|
// unless this function returns an error.
|
||||||
|
// (The cleanup operand of each return
|
||||||
|
// statement below is ignored.)
|
||||||
|
defer func() {
|
||||||
|
cleanup = func() {
|
||||||
|
os.RemoveAll(dir)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
cleanup()
|
||||||
|
cleanup = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Write each map entry to a temporary file.
|
||||||
|
overlays := make(map[string]string)
|
||||||
|
for k, v := range overlay {
|
||||||
|
// Use a unique basename for each file (001-foo.go),
|
||||||
|
// to avoid creating nested directories.
|
||||||
|
base := fmt.Sprintf("%d-%s", 1+len(overlays), filepath.Base(k))
|
||||||
|
filename := filepath.Join(dir, base)
|
||||||
|
err := os.WriteFile(filename, v, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
overlays[k] = filename
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the JSON overlay file that maps logical file names to temp files.
|
||||||
|
//
|
||||||
|
// OverlayJSON is the format overlay files are expected to be in.
|
||||||
|
// The Replace map maps from overlaid paths to replacement paths:
|
||||||
|
// the Go command will forward all reads trying to open
|
||||||
|
// each overlaid path to its replacement path, or consider the overlaid
|
||||||
|
// path not to exist if the replacement path is empty.
|
||||||
|
//
|
||||||
|
// From golang/go#39958.
|
||||||
|
type OverlayJSON struct {
|
||||||
|
Replace map[string]string `json:"replace,omitempty"`
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(OverlayJSON{Replace: overlays})
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
filename = filepath.Join(dir, "overlay.json")
|
||||||
|
if err := os.WriteFile(filename, b, 0666); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return filename, nil, nil
|
||||||
|
}
|
||||||
|
54
vendor/golang.org/x/tools/internal/gocommand/vendor.go
generated
vendored
54
vendor/golang.org/x/tools/internal/gocommand/vendor.go
generated
vendored
@ -107,3 +107,57 @@ func getMainModuleAnd114(ctx context.Context, inv Invocation, r *Runner) (*Modul
|
|||||||
}
|
}
|
||||||
return mod, lines[4] == "go1.14", nil
|
return mod, lines[4] == "go1.14", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WorkspaceVendorEnabled reports whether workspace vendoring is enabled. It takes a *Runner to execute Go commands
|
||||||
|
// with the supplied context.Context and Invocation. The Invocation can contain pre-defined fields,
|
||||||
|
// of which only Verb and Args are modified to run the appropriate Go command.
|
||||||
|
// Inspired by setDefaultBuildMod in modload/init.go
|
||||||
|
func WorkspaceVendorEnabled(ctx context.Context, inv Invocation, r *Runner) (bool, []*ModuleJSON, error) {
|
||||||
|
inv.Verb = "env"
|
||||||
|
inv.Args = []string{"GOWORK"}
|
||||||
|
stdout, err := r.Run(ctx, inv)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
goWork := string(bytes.TrimSpace(stdout.Bytes()))
|
||||||
|
if fi, err := os.Stat(filepath.Join(filepath.Dir(goWork), "vendor")); err == nil && fi.IsDir() {
|
||||||
|
mainMods, err := getWorkspaceMainModules(ctx, inv, r)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
return true, mainMods, nil
|
||||||
|
}
|
||||||
|
return false, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getWorkspaceMainModules gets the main modules' information.
|
||||||
|
// This is the information needed to figure out if vendoring should be enabled.
|
||||||
|
func getWorkspaceMainModules(ctx context.Context, inv Invocation, r *Runner) ([]*ModuleJSON, error) {
|
||||||
|
const format = `{{.Path}}
|
||||||
|
{{.Dir}}
|
||||||
|
{{.GoMod}}
|
||||||
|
{{.GoVersion}}
|
||||||
|
`
|
||||||
|
inv.Verb = "list"
|
||||||
|
inv.Args = []string{"-m", "-f", format}
|
||||||
|
stdout, err := r.Run(ctx, inv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(strings.TrimSuffix(stdout.String(), "\n"), "\n")
|
||||||
|
if len(lines) < 4 {
|
||||||
|
return nil, fmt.Errorf("unexpected stdout: %q", stdout.String())
|
||||||
|
}
|
||||||
|
mods := make([]*ModuleJSON, 0, len(lines)/4)
|
||||||
|
for i := 0; i < len(lines); i += 4 {
|
||||||
|
mods = append(mods, &ModuleJSON{
|
||||||
|
Path: lines[i],
|
||||||
|
Dir: lines[i+1],
|
||||||
|
GoMod: lines[i+2],
|
||||||
|
GoVersion: lines[i+3],
|
||||||
|
Main: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return mods, nil
|
||||||
|
}
|
||||||
|
8
vendor/golang.org/x/tools/internal/packagesinternal/packages.go
generated
vendored
8
vendor/golang.org/x/tools/internal/packagesinternal/packages.go
generated
vendored
@ -5,10 +5,6 @@
|
|||||||
// Package packagesinternal exposes internal-only fields from go/packages.
|
// Package packagesinternal exposes internal-only fields from go/packages.
|
||||||
package packagesinternal
|
package packagesinternal
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/tools/internal/gocommand"
|
|
||||||
)
|
|
||||||
|
|
||||||
var GetForTest = func(p interface{}) string { return "" }
|
var GetForTest = func(p interface{}) string { return "" }
|
||||||
var GetDepsErrors = func(p interface{}) []*PackageError { return nil }
|
var GetDepsErrors = func(p interface{}) []*PackageError { return nil }
|
||||||
|
|
||||||
@ -18,10 +14,6 @@ type PackageError struct {
|
|||||||
Err string // the error itself
|
Err string // the error itself
|
||||||
}
|
}
|
||||||
|
|
||||||
var GetGoCmdRunner = func(config interface{}) *gocommand.Runner { return nil }
|
|
||||||
|
|
||||||
var SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) {}
|
|
||||||
|
|
||||||
var TypecheckCgo int
|
var TypecheckCgo int
|
||||||
var DepsErrors int // must be set as a LoadMode to call GetDepsErrors
|
var DepsErrors int // must be set as a LoadMode to call GetDepsErrors
|
||||||
var ForTest int // must be set as a LoadMode to call GetForTest
|
var ForTest int // must be set as a LoadMode to call GetForTest
|
||||||
|
34
vendor/golang.org/x/tools/internal/pkgbits/decoder.go
generated
vendored
34
vendor/golang.org/x/tools/internal/pkgbits/decoder.go
generated
vendored
@ -21,7 +21,7 @@ import (
|
|||||||
// export data.
|
// export data.
|
||||||
type PkgDecoder struct {
|
type PkgDecoder struct {
|
||||||
// version is the file format version.
|
// version is the file format version.
|
||||||
version uint32
|
version Version
|
||||||
|
|
||||||
// sync indicates whether the file uses sync markers.
|
// sync indicates whether the file uses sync markers.
|
||||||
sync bool
|
sync bool
|
||||||
@ -68,8 +68,6 @@ func (pr *PkgDecoder) SyncMarkers() bool { return pr.sync }
|
|||||||
// NewPkgDecoder returns a PkgDecoder initialized to read the Unified
|
// NewPkgDecoder returns a PkgDecoder initialized to read the Unified
|
||||||
// IR export data from input. pkgPath is the package path for the
|
// IR export data from input. pkgPath is the package path for the
|
||||||
// compilation unit that produced the export data.
|
// compilation unit that produced the export data.
|
||||||
//
|
|
||||||
// TODO(mdempsky): Remove pkgPath parameter; unneeded since CL 391014.
|
|
||||||
func NewPkgDecoder(pkgPath, input string) PkgDecoder {
|
func NewPkgDecoder(pkgPath, input string) PkgDecoder {
|
||||||
pr := PkgDecoder{
|
pr := PkgDecoder{
|
||||||
pkgPath: pkgPath,
|
pkgPath: pkgPath,
|
||||||
@ -80,14 +78,15 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder {
|
|||||||
|
|
||||||
r := strings.NewReader(input)
|
r := strings.NewReader(input)
|
||||||
|
|
||||||
assert(binary.Read(r, binary.LittleEndian, &pr.version) == nil)
|
var ver uint32
|
||||||
|
assert(binary.Read(r, binary.LittleEndian, &ver) == nil)
|
||||||
|
pr.version = Version(ver)
|
||||||
|
|
||||||
switch pr.version {
|
if pr.version >= numVersions {
|
||||||
default:
|
panic(fmt.Errorf("cannot decode %q, export data version %d is greater than maximum supported version %d", pkgPath, pr.version, numVersions-1))
|
||||||
panic(fmt.Errorf("unsupported version: %v", pr.version))
|
}
|
||||||
case 0:
|
|
||||||
// no flags
|
if pr.version.Has(Flags) {
|
||||||
case 1:
|
|
||||||
var flags uint32
|
var flags uint32
|
||||||
assert(binary.Read(r, binary.LittleEndian, &flags) == nil)
|
assert(binary.Read(r, binary.LittleEndian, &flags) == nil)
|
||||||
pr.sync = flags&flagSyncMarkers != 0
|
pr.sync = flags&flagSyncMarkers != 0
|
||||||
@ -102,7 +101,9 @@ func NewPkgDecoder(pkgPath, input string) PkgDecoder {
|
|||||||
assert(err == nil)
|
assert(err == nil)
|
||||||
|
|
||||||
pr.elemData = input[pos:]
|
pr.elemData = input[pos:]
|
||||||
assert(len(pr.elemData)-8 == int(pr.elemEnds[len(pr.elemEnds)-1]))
|
|
||||||
|
const fingerprintSize = 8
|
||||||
|
assert(len(pr.elemData)-fingerprintSize == int(pr.elemEnds[len(pr.elemEnds)-1]))
|
||||||
|
|
||||||
return pr
|
return pr
|
||||||
}
|
}
|
||||||
@ -136,7 +137,7 @@ func (pr *PkgDecoder) AbsIdx(k RelocKind, idx Index) int {
|
|||||||
absIdx += int(pr.elemEndsEnds[k-1])
|
absIdx += int(pr.elemEndsEnds[k-1])
|
||||||
}
|
}
|
||||||
if absIdx >= int(pr.elemEndsEnds[k]) {
|
if absIdx >= int(pr.elemEndsEnds[k]) {
|
||||||
errorf("%v:%v is out of bounds; %v", k, idx, pr.elemEndsEnds)
|
panicf("%v:%v is out of bounds; %v", k, idx, pr.elemEndsEnds)
|
||||||
}
|
}
|
||||||
return absIdx
|
return absIdx
|
||||||
}
|
}
|
||||||
@ -193,9 +194,7 @@ func (pr *PkgDecoder) NewDecoderRaw(k RelocKind, idx Index) Decoder {
|
|||||||
Idx: idx,
|
Idx: idx,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mdempsky) r.data.Reset(...) after #44505 is resolved.
|
r.Data.Reset(pr.DataIdx(k, idx))
|
||||||
r.Data = *strings.NewReader(pr.DataIdx(k, idx))
|
|
||||||
|
|
||||||
r.Sync(SyncRelocs)
|
r.Sync(SyncRelocs)
|
||||||
r.Relocs = make([]RelocEnt, r.Len())
|
r.Relocs = make([]RelocEnt, r.Len())
|
||||||
for i := range r.Relocs {
|
for i := range r.Relocs {
|
||||||
@ -244,7 +243,7 @@ type Decoder struct {
|
|||||||
|
|
||||||
func (r *Decoder) checkErr(err error) {
|
func (r *Decoder) checkErr(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorf("unexpected decoding error: %w", err)
|
panicf("unexpected decoding error: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,3 +514,6 @@ func (pr *PkgDecoder) PeekObj(idx Index) (string, string, CodeObj) {
|
|||||||
|
|
||||||
return path, name, tag
|
return path, name, tag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Version reports the version of the bitstream.
|
||||||
|
func (w *Decoder) Version() Version { return w.common.version }
|
||||||
|
43
vendor/golang.org/x/tools/internal/pkgbits/encoder.go
generated
vendored
43
vendor/golang.org/x/tools/internal/pkgbits/encoder.go
generated
vendored
@ -12,18 +12,15 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// currentVersion is the current version number.
|
|
||||||
//
|
|
||||||
// - v0: initial prototype
|
|
||||||
//
|
|
||||||
// - v1: adds the flags uint32 word
|
|
||||||
const currentVersion uint32 = 1
|
|
||||||
|
|
||||||
// A PkgEncoder provides methods for encoding a package's Unified IR
|
// A PkgEncoder provides methods for encoding a package's Unified IR
|
||||||
// export data.
|
// export data.
|
||||||
type PkgEncoder struct {
|
type PkgEncoder struct {
|
||||||
|
// version of the bitstream.
|
||||||
|
version Version
|
||||||
|
|
||||||
// elems holds the bitstream for previously encoded elements.
|
// elems holds the bitstream for previously encoded elements.
|
||||||
elems [numRelocs][]string
|
elems [numRelocs][]string
|
||||||
|
|
||||||
@ -47,8 +44,9 @@ func (pw *PkgEncoder) SyncMarkers() bool { return pw.syncFrames >= 0 }
|
|||||||
// export data files, but can help diagnosing desync errors in
|
// export data files, but can help diagnosing desync errors in
|
||||||
// higher-level Unified IR reader/writer code. If syncFrames is
|
// higher-level Unified IR reader/writer code. If syncFrames is
|
||||||
// negative, then sync markers are omitted entirely.
|
// negative, then sync markers are omitted entirely.
|
||||||
func NewPkgEncoder(syncFrames int) PkgEncoder {
|
func NewPkgEncoder(version Version, syncFrames int) PkgEncoder {
|
||||||
return PkgEncoder{
|
return PkgEncoder{
|
||||||
|
version: version,
|
||||||
stringsIdx: make(map[string]Index),
|
stringsIdx: make(map[string]Index),
|
||||||
syncFrames: syncFrames,
|
syncFrames: syncFrames,
|
||||||
}
|
}
|
||||||
@ -64,13 +62,15 @@ func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) {
|
|||||||
assert(binary.Write(out, binary.LittleEndian, x) == nil)
|
assert(binary.Write(out, binary.LittleEndian, x) == nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
writeUint32(currentVersion)
|
writeUint32(uint32(pw.version))
|
||||||
|
|
||||||
var flags uint32
|
if pw.version.Has(Flags) {
|
||||||
if pw.SyncMarkers() {
|
var flags uint32
|
||||||
flags |= flagSyncMarkers
|
if pw.SyncMarkers() {
|
||||||
|
flags |= flagSyncMarkers
|
||||||
|
}
|
||||||
|
writeUint32(flags)
|
||||||
}
|
}
|
||||||
writeUint32(flags)
|
|
||||||
|
|
||||||
// Write elemEndsEnds.
|
// Write elemEndsEnds.
|
||||||
var sum uint32
|
var sum uint32
|
||||||
@ -159,7 +159,7 @@ type Encoder struct {
|
|||||||
|
|
||||||
// Flush finalizes the element's bitstream and returns its Index.
|
// Flush finalizes the element's bitstream and returns its Index.
|
||||||
func (w *Encoder) Flush() Index {
|
func (w *Encoder) Flush() Index {
|
||||||
var sb bytes.Buffer // TODO(mdempsky): strings.Builder after #44505 is resolved
|
var sb strings.Builder
|
||||||
|
|
||||||
// Backup the data so we write the relocations at the front.
|
// Backup the data so we write the relocations at the front.
|
||||||
var tmp bytes.Buffer
|
var tmp bytes.Buffer
|
||||||
@ -189,7 +189,7 @@ func (w *Encoder) Flush() Index {
|
|||||||
|
|
||||||
func (w *Encoder) checkErr(err error) {
|
func (w *Encoder) checkErr(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorf("unexpected encoding error: %v", err)
|
panicf("unexpected encoding error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,8 +320,14 @@ func (w *Encoder) Code(c Code) {
|
|||||||
// section (if not already present), and then writing a relocation
|
// section (if not already present), and then writing a relocation
|
||||||
// into the element bitstream.
|
// into the element bitstream.
|
||||||
func (w *Encoder) String(s string) {
|
func (w *Encoder) String(s string) {
|
||||||
|
w.StringRef(w.p.StringIdx(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringRef writes a reference to the given index, which must be a
|
||||||
|
// previously encoded string value.
|
||||||
|
func (w *Encoder) StringRef(idx Index) {
|
||||||
w.Sync(SyncString)
|
w.Sync(SyncString)
|
||||||
w.Reloc(RelocString, w.p.StringIdx(s))
|
w.Reloc(RelocString, idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strings encodes and writes a variable-length slice of strings into
|
// Strings encodes and writes a variable-length slice of strings into
|
||||||
@ -348,7 +354,7 @@ func (w *Encoder) Value(val constant.Value) {
|
|||||||
func (w *Encoder) scalar(val constant.Value) {
|
func (w *Encoder) scalar(val constant.Value) {
|
||||||
switch v := constant.Val(val).(type) {
|
switch v := constant.Val(val).(type) {
|
||||||
default:
|
default:
|
||||||
errorf("unhandled %v (%v)", val, val.Kind())
|
panicf("unhandled %v (%v)", val, val.Kind())
|
||||||
case bool:
|
case bool:
|
||||||
w.Code(ValBool)
|
w.Code(ValBool)
|
||||||
w.Bool(v)
|
w.Bool(v)
|
||||||
@ -381,3 +387,6 @@ func (w *Encoder) bigFloat(v *big.Float) {
|
|||||||
b := v.Append(nil, 'p', -1)
|
b := v.Append(nil, 'p', -1)
|
||||||
w.String(string(b)) // TODO: More efficient encoding.
|
w.String(string(b)) // TODO: More efficient encoding.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Version reports the version of the bitstream.
|
||||||
|
func (w *Encoder) Version() Version { return w.p.version }
|
||||||
|
21
vendor/golang.org/x/tools/internal/pkgbits/frames_go1.go
generated
vendored
21
vendor/golang.org/x/tools/internal/pkgbits/frames_go1.go
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
// Copyright 2021 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.7
|
|
||||||
// +build !go1.7
|
|
||||||
|
|
||||||
// TODO(mdempsky): Remove after #44505 is resolved
|
|
||||||
|
|
||||||
package pkgbits
|
|
||||||
|
|
||||||
import "runtime"
|
|
||||||
|
|
||||||
func walkFrames(pcs []uintptr, visit frameVisitor) {
|
|
||||||
for _, pc := range pcs {
|
|
||||||
fn := runtime.FuncForPC(pc)
|
|
||||||
file, line := fn.FileLine(pc)
|
|
||||||
|
|
||||||
visit(file, line, fn.Name(), pc-fn.Entry())
|
|
||||||
}
|
|
||||||
}
|
|
28
vendor/golang.org/x/tools/internal/pkgbits/frames_go17.go
generated
vendored
28
vendor/golang.org/x/tools/internal/pkgbits/frames_go17.go
generated
vendored
@ -1,28 +0,0 @@
|
|||||||
// Copyright 2021 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.7
|
|
||||||
// +build go1.7
|
|
||||||
|
|
||||||
package pkgbits
|
|
||||||
|
|
||||||
import "runtime"
|
|
||||||
|
|
||||||
// walkFrames calls visit for each call frame represented by pcs.
|
|
||||||
//
|
|
||||||
// pcs should be a slice of PCs, as returned by runtime.Callers.
|
|
||||||
func walkFrames(pcs []uintptr, visit frameVisitor) {
|
|
||||||
if len(pcs) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
frames := runtime.CallersFrames(pcs)
|
|
||||||
for {
|
|
||||||
frame, more := frames.Next()
|
|
||||||
visit(frame.File, frame.Line, frame.Function, frame.PC-frame.Entry)
|
|
||||||
if !more {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
2
vendor/golang.org/x/tools/internal/pkgbits/support.go
generated
vendored
2
vendor/golang.org/x/tools/internal/pkgbits/support.go
generated
vendored
@ -12,6 +12,6 @@ func assert(b bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func errorf(format string, args ...interface{}) {
|
func panicf(format string, args ...any) {
|
||||||
panic(fmt.Errorf(format, args...))
|
panic(fmt.Errorf(format, args...))
|
||||||
}
|
}
|
||||||
|
23
vendor/golang.org/x/tools/internal/pkgbits/sync.go
generated
vendored
23
vendor/golang.org/x/tools/internal/pkgbits/sync.go
generated
vendored
@ -6,6 +6,7 @@ package pkgbits
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,6 +24,24 @@ func fmtFrames(pcs ...uintptr) []string {
|
|||||||
|
|
||||||
type frameVisitor func(file string, line int, name string, offset uintptr)
|
type frameVisitor func(file string, line int, name string, offset uintptr)
|
||||||
|
|
||||||
|
// walkFrames calls visit for each call frame represented by pcs.
|
||||||
|
//
|
||||||
|
// pcs should be a slice of PCs, as returned by runtime.Callers.
|
||||||
|
func walkFrames(pcs []uintptr, visit frameVisitor) {
|
||||||
|
if len(pcs) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
frames := runtime.CallersFrames(pcs)
|
||||||
|
for {
|
||||||
|
frame, more := frames.Next()
|
||||||
|
visit(frame.File, frame.Line, frame.Function, frame.PC-frame.Entry)
|
||||||
|
if !more {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SyncMarker is an enum type that represents markers that may be
|
// SyncMarker is an enum type that represents markers that may be
|
||||||
// written to export data to ensure the reader and writer stay
|
// written to export data to ensure the reader and writer stay
|
||||||
// synchronized.
|
// synchronized.
|
||||||
@ -110,4 +129,8 @@ const (
|
|||||||
SyncStmtsEnd
|
SyncStmtsEnd
|
||||||
SyncLabel
|
SyncLabel
|
||||||
SyncOptLabel
|
SyncOptLabel
|
||||||
|
|
||||||
|
SyncMultiExpr
|
||||||
|
SyncRType
|
||||||
|
SyncConvRTTI
|
||||||
)
|
)
|
||||||
|
7
vendor/golang.org/x/tools/internal/pkgbits/syncmarker_string.go
generated
vendored
7
vendor/golang.org/x/tools/internal/pkgbits/syncmarker_string.go
generated
vendored
@ -74,11 +74,14 @@ func _() {
|
|||||||
_ = x[SyncStmtsEnd-64]
|
_ = x[SyncStmtsEnd-64]
|
||||||
_ = x[SyncLabel-65]
|
_ = x[SyncLabel-65]
|
||||||
_ = x[SyncOptLabel-66]
|
_ = x[SyncOptLabel-66]
|
||||||
|
_ = x[SyncMultiExpr-67]
|
||||||
|
_ = x[SyncRType-68]
|
||||||
|
_ = x[SyncConvRTTI-69]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _SyncMarker_name = "EOFBoolInt64Uint64StringValueValRelocsRelocUseRelocPublicPosPosBaseObjectObject1PkgPkgDefMethodTypeTypeIdxTypeParamNamesSignatureParamsParamCodeObjSymLocalIdentSelectorPrivateFuncExtVarExtTypeExtPragmaExprListExprsExprExprTypeAssignOpFuncLitCompLitDeclFuncBodyOpenScopeCloseScopeCloseAnotherScopeDeclNamesDeclNameStmtsBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtUseObjLocalAddLocalLinknameStmt1StmtsEndLabelOptLabel"
|
const _SyncMarker_name = "EOFBoolInt64Uint64StringValueValRelocsRelocUseRelocPublicPosPosBaseObjectObject1PkgPkgDefMethodTypeTypeIdxTypeParamNamesSignatureParamsParamCodeObjSymLocalIdentSelectorPrivateFuncExtVarExtTypeExtPragmaExprListExprsExprExprTypeAssignOpFuncLitCompLitDeclFuncBodyOpenScopeCloseScopeCloseAnotherScopeDeclNamesDeclNameStmtsBlockStmtIfStmtForStmtSwitchStmtRangeStmtCaseClauseCommClauseSelectStmtDeclsLabeledStmtUseObjLocalAddLocalLinknameStmt1StmtsEndLabelOptLabelMultiExprRTypeConvRTTI"
|
||||||
|
|
||||||
var _SyncMarker_index = [...]uint16{0, 3, 7, 12, 18, 24, 29, 32, 38, 43, 51, 57, 60, 67, 73, 80, 83, 89, 95, 99, 106, 120, 129, 135, 140, 147, 150, 160, 168, 175, 182, 188, 195, 201, 209, 214, 218, 226, 232, 234, 241, 248, 252, 260, 269, 279, 296, 305, 313, 318, 327, 333, 340, 350, 359, 369, 379, 389, 394, 405, 416, 424, 432, 437, 445, 450, 458}
|
var _SyncMarker_index = [...]uint16{0, 3, 7, 12, 18, 24, 29, 32, 38, 43, 51, 57, 60, 67, 73, 80, 83, 89, 95, 99, 106, 120, 129, 135, 140, 147, 150, 160, 168, 175, 182, 188, 195, 201, 209, 214, 218, 226, 232, 234, 241, 248, 252, 260, 269, 279, 296, 305, 313, 318, 327, 333, 340, 350, 359, 369, 379, 389, 394, 405, 416, 424, 432, 437, 445, 450, 458, 467, 472, 480}
|
||||||
|
|
||||||
func (i SyncMarker) String() string {
|
func (i SyncMarker) String() string {
|
||||||
i -= 1
|
i -= 1
|
||||||
|
85
vendor/golang.org/x/tools/internal/pkgbits/version.go
generated
vendored
Normal file
85
vendor/golang.org/x/tools/internal/pkgbits/version.go
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package pkgbits
|
||||||
|
|
||||||
|
// Version indicates a version of a unified IR bitstream.
|
||||||
|
// Each Version indicates the addition, removal, or change of
|
||||||
|
// new data in the bitstream.
|
||||||
|
//
|
||||||
|
// These are serialized to disk and the interpretation remains fixed.
|
||||||
|
type Version uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
// V0: initial prototype.
|
||||||
|
//
|
||||||
|
// All data that is not assigned a Field is in version V0
|
||||||
|
// and has not been deprecated.
|
||||||
|
V0 Version = iota
|
||||||
|
|
||||||
|
// V1: adds the Flags uint32 word
|
||||||
|
V1
|
||||||
|
|
||||||
|
// V2: removes unused legacy fields and supports type parameters for aliases.
|
||||||
|
// - remove the legacy "has init" bool from the public root
|
||||||
|
// - remove obj's "derived func instance" bool
|
||||||
|
// - add a TypeParamNames field to ObjAlias
|
||||||
|
// - remove derived info "needed" bool
|
||||||
|
V2
|
||||||
|
|
||||||
|
numVersions = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
// Field denotes a unit of data in the serialized unified IR bitstream.
|
||||||
|
// It is conceptually a like field in a structure.
|
||||||
|
//
|
||||||
|
// We only really need Fields when the data may or may not be present
|
||||||
|
// in a stream based on the Version of the bitstream.
|
||||||
|
//
|
||||||
|
// Unlike much of pkgbits, Fields are not serialized and
|
||||||
|
// can change values as needed.
|
||||||
|
type Field int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Flags in a uint32 in the header of a bitstream
|
||||||
|
// that is used to indicate whether optional features are enabled.
|
||||||
|
Flags Field = iota
|
||||||
|
|
||||||
|
// Deprecated: HasInit was a bool indicating whether a package
|
||||||
|
// has any init functions.
|
||||||
|
HasInit
|
||||||
|
|
||||||
|
// Deprecated: DerivedFuncInstance was a bool indicating
|
||||||
|
// whether an object was a function instance.
|
||||||
|
DerivedFuncInstance
|
||||||
|
|
||||||
|
// ObjAlias has a list of TypeParamNames.
|
||||||
|
AliasTypeParamNames
|
||||||
|
|
||||||
|
// Deprecated: DerivedInfoNeeded was a bool indicating
|
||||||
|
// whether a type was a derived type.
|
||||||
|
DerivedInfoNeeded
|
||||||
|
|
||||||
|
numFields = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
// introduced is the version a field was added.
|
||||||
|
var introduced = [numFields]Version{
|
||||||
|
Flags: V1,
|
||||||
|
AliasTypeParamNames: V2,
|
||||||
|
}
|
||||||
|
|
||||||
|
// removed is the version a field was removed in or 0 for fields
|
||||||
|
// that have not yet been deprecated.
|
||||||
|
// (So removed[f]-1 is the last version it is included in.)
|
||||||
|
var removed = [numFields]Version{
|
||||||
|
HasInit: V2,
|
||||||
|
DerivedFuncInstance: V2,
|
||||||
|
DerivedInfoNeeded: V2,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has reports whether field f is present in a bitstream at version v.
|
||||||
|
func (v Version) Has(f Field) bool {
|
||||||
|
return introduced[f] <= v && (v < removed[f] || removed[f] == V0)
|
||||||
|
}
|
17431
vendor/golang.org/x/tools/internal/stdlib/manifest.go
generated
vendored
Normal file
17431
vendor/golang.org/x/tools/internal/stdlib/manifest.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
97
vendor/golang.org/x/tools/internal/stdlib/stdlib.go
generated
vendored
Normal file
97
vendor/golang.org/x/tools/internal/stdlib/stdlib.go
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// Copyright 2022 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:generate go run generate.go
|
||||||
|
|
||||||
|
// Package stdlib provides a table of all exported symbols in the
|
||||||
|
// standard library, along with the version at which they first
|
||||||
|
// appeared.
|
||||||
|
package stdlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Symbol struct {
|
||||||
|
Name string
|
||||||
|
Kind Kind
|
||||||
|
Version Version // Go version that first included the symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Kind indicates the kind of a symbol:
|
||||||
|
// function, variable, constant, type, and so on.
|
||||||
|
type Kind int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
Invalid Kind = iota // Example name:
|
||||||
|
Type // "Buffer"
|
||||||
|
Func // "Println"
|
||||||
|
Var // "EOF"
|
||||||
|
Const // "Pi"
|
||||||
|
Field // "Point.X"
|
||||||
|
Method // "(*Buffer).Grow"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (kind Kind) String() string {
|
||||||
|
return [...]string{
|
||||||
|
Invalid: "invalid",
|
||||||
|
Type: "type",
|
||||||
|
Func: "func",
|
||||||
|
Var: "var",
|
||||||
|
Const: "const",
|
||||||
|
Field: "field",
|
||||||
|
Method: "method",
|
||||||
|
}[kind]
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Version represents a version of Go of the form "go1.%d".
|
||||||
|
type Version int8
|
||||||
|
|
||||||
|
// String returns a version string of the form "go1.23", without allocating.
|
||||||
|
func (v Version) String() string { return versions[v] }
|
||||||
|
|
||||||
|
var versions [30]string // (increase constant as needed)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
for i := range versions {
|
||||||
|
versions[i] = fmt.Sprintf("go1.%d", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasPackage reports whether the specified package path is part of
|
||||||
|
// the standard library's public API.
|
||||||
|
func HasPackage(path string) bool {
|
||||||
|
_, ok := PackageSymbols[path]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// SplitField splits the field symbol name into type and field
|
||||||
|
// components. It must be called only on Field symbols.
|
||||||
|
//
|
||||||
|
// Example: "File.Package" -> ("File", "Package")
|
||||||
|
func (sym *Symbol) SplitField() (typename, name string) {
|
||||||
|
if sym.Kind != Field {
|
||||||
|
panic("not a field")
|
||||||
|
}
|
||||||
|
typename, name, _ = strings.Cut(sym.Name, ".")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SplitMethod splits the method symbol name into pointer, receiver,
|
||||||
|
// and method components. It must be called only on Method symbols.
|
||||||
|
//
|
||||||
|
// Example: "(*Buffer).Grow" -> (true, "Buffer", "Grow")
|
||||||
|
func (sym *Symbol) SplitMethod() (ptr bool, recv, name string) {
|
||||||
|
if sym.Kind != Method {
|
||||||
|
panic("not a method")
|
||||||
|
}
|
||||||
|
recv, name, _ = strings.Cut(sym.Name, ".")
|
||||||
|
recv = recv[len("(") : len(recv)-len(")")]
|
||||||
|
ptr = recv[0] == '*'
|
||||||
|
if ptr {
|
||||||
|
recv = recv[len("*"):]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
151
vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go
generated
vendored
151
vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go
generated
vendored
@ -1,151 +0,0 @@
|
|||||||
// Copyright 2023 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 tokeninternal provides access to some internal features of the token
|
|
||||||
// package.
|
|
||||||
package tokeninternal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/token"
|
|
||||||
"sort"
|
|
||||||
"sync"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetLines returns the table of line-start offsets from a token.File.
|
|
||||||
func GetLines(file *token.File) []int {
|
|
||||||
// token.File has a Lines method on Go 1.21 and later.
|
|
||||||
if file, ok := (interface{})(file).(interface{ Lines() []int }); ok {
|
|
||||||
return file.Lines()
|
|
||||||
}
|
|
||||||
|
|
||||||
// This declaration must match that of token.File.
|
|
||||||
// This creates a risk of dependency skew.
|
|
||||||
// For now we check that the size of the two
|
|
||||||
// declarations is the same, on the (fragile) assumption
|
|
||||||
// that future changes would add fields.
|
|
||||||
type tokenFile119 struct {
|
|
||||||
_ string
|
|
||||||
_ int
|
|
||||||
_ int
|
|
||||||
mu sync.Mutex // we're not complete monsters
|
|
||||||
lines []int
|
|
||||||
_ []struct{}
|
|
||||||
}
|
|
||||||
type tokenFile118 struct {
|
|
||||||
_ *token.FileSet // deleted in go1.19
|
|
||||||
tokenFile119
|
|
||||||
}
|
|
||||||
|
|
||||||
type uP = unsafe.Pointer
|
|
||||||
switch unsafe.Sizeof(*file) {
|
|
||||||
case unsafe.Sizeof(tokenFile118{}):
|
|
||||||
var ptr *tokenFile118
|
|
||||||
*(*uP)(uP(&ptr)) = uP(file)
|
|
||||||
ptr.mu.Lock()
|
|
||||||
defer ptr.mu.Unlock()
|
|
||||||
return ptr.lines
|
|
||||||
|
|
||||||
case unsafe.Sizeof(tokenFile119{}):
|
|
||||||
var ptr *tokenFile119
|
|
||||||
*(*uP)(uP(&ptr)) = uP(file)
|
|
||||||
ptr.mu.Lock()
|
|
||||||
defer ptr.mu.Unlock()
|
|
||||||
return ptr.lines
|
|
||||||
|
|
||||||
default:
|
|
||||||
panic("unexpected token.File size")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddExistingFiles adds the specified files to the FileSet if they
|
|
||||||
// are not already present. It panics if any pair of files in the
|
|
||||||
// resulting FileSet would overlap.
|
|
||||||
func AddExistingFiles(fset *token.FileSet, files []*token.File) {
|
|
||||||
// Punch through the FileSet encapsulation.
|
|
||||||
type tokenFileSet struct {
|
|
||||||
// This type remained essentially consistent from go1.16 to go1.21.
|
|
||||||
mutex sync.RWMutex
|
|
||||||
base int
|
|
||||||
files []*token.File
|
|
||||||
_ *token.File // changed to atomic.Pointer[token.File] in go1.19
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the size of token.FileSet changes, this will fail to compile.
|
|
||||||
const delta = int64(unsafe.Sizeof(tokenFileSet{})) - int64(unsafe.Sizeof(token.FileSet{}))
|
|
||||||
var _ [-delta * delta]int
|
|
||||||
|
|
||||||
type uP = unsafe.Pointer
|
|
||||||
var ptr *tokenFileSet
|
|
||||||
*(*uP)(uP(&ptr)) = uP(fset)
|
|
||||||
ptr.mutex.Lock()
|
|
||||||
defer ptr.mutex.Unlock()
|
|
||||||
|
|
||||||
// Merge and sort.
|
|
||||||
newFiles := append(ptr.files, files...)
|
|
||||||
sort.Slice(newFiles, func(i, j int) bool {
|
|
||||||
return newFiles[i].Base() < newFiles[j].Base()
|
|
||||||
})
|
|
||||||
|
|
||||||
// Reject overlapping files.
|
|
||||||
// Discard adjacent identical files.
|
|
||||||
out := newFiles[:0]
|
|
||||||
for i, file := range newFiles {
|
|
||||||
if i > 0 {
|
|
||||||
prev := newFiles[i-1]
|
|
||||||
if file == prev {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if prev.Base()+prev.Size()+1 > file.Base() {
|
|
||||||
panic(fmt.Sprintf("file %s (%d-%d) overlaps with file %s (%d-%d)",
|
|
||||||
prev.Name(), prev.Base(), prev.Base()+prev.Size(),
|
|
||||||
file.Name(), file.Base(), file.Base()+file.Size()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out = append(out, file)
|
|
||||||
}
|
|
||||||
newFiles = out
|
|
||||||
|
|
||||||
ptr.files = newFiles
|
|
||||||
|
|
||||||
// Advance FileSet.Base().
|
|
||||||
if len(newFiles) > 0 {
|
|
||||||
last := newFiles[len(newFiles)-1]
|
|
||||||
newBase := last.Base() + last.Size() + 1
|
|
||||||
if ptr.base < newBase {
|
|
||||||
ptr.base = newBase
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileSetFor returns a new FileSet containing a sequence of new Files with
|
|
||||||
// the same base, size, and line as the input files, for use in APIs that
|
|
||||||
// require a FileSet.
|
|
||||||
//
|
|
||||||
// Precondition: the input files must be non-overlapping, and sorted in order
|
|
||||||
// of their Base.
|
|
||||||
func FileSetFor(files ...*token.File) *token.FileSet {
|
|
||||||
fset := token.NewFileSet()
|
|
||||||
for _, f := range files {
|
|
||||||
f2 := fset.AddFile(f.Name(), f.Base(), f.Size())
|
|
||||||
lines := GetLines(f)
|
|
||||||
f2.SetLines(lines)
|
|
||||||
}
|
|
||||||
return fset
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloneFileSet creates a new FileSet holding all files in fset. It does not
|
|
||||||
// create copies of the token.Files in fset: they are added to the resulting
|
|
||||||
// FileSet unmodified.
|
|
||||||
func CloneFileSet(fset *token.FileSet) *token.FileSet {
|
|
||||||
var files []*token.File
|
|
||||||
fset.Iterate(func(f *token.File) bool {
|
|
||||||
files = append(files, f)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
newFileSet := token.NewFileSet()
|
|
||||||
AddExistingFiles(newFileSet, files)
|
|
||||||
return newFileSet
|
|
||||||
}
|
|
102
vendor/golang.org/x/tools/internal/typeparams/common.go
generated
vendored
102
vendor/golang.org/x/tools/internal/typeparams/common.go
generated
vendored
@ -2,20 +2,10 @@
|
|||||||
// 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 typeparams contains common utilities for writing tools that interact
|
// Package typeparams contains common utilities for writing tools that
|
||||||
// with generic Go code, as introduced with Go 1.18.
|
// interact with generic Go code, as introduced with Go 1.18. It
|
||||||
//
|
// supplements the standard library APIs. Notably, the StructuralTerms
|
||||||
// Many of the types and functions in this package are proxies for the new APIs
|
// API computes a minimal representation of the structural
|
||||||
// introduced in the standard library with Go 1.18. For example, the
|
|
||||||
// typeparams.Union type is an alias for go/types.Union, and the ForTypeSpec
|
|
||||||
// function returns the value of the go/ast.TypeSpec.TypeParams field. At Go
|
|
||||||
// versions older than 1.18 these helpers are implemented as stubs, allowing
|
|
||||||
// users of this package to write code that handles generic constructs inline,
|
|
||||||
// even if the Go version being used to compile does not support generics.
|
|
||||||
//
|
|
||||||
// Additionally, this package contains common utilities for working with the
|
|
||||||
// new generic constructs, to supplement the standard library APIs. Notably,
|
|
||||||
// the StructuralTerms API computes a minimal representation of the structural
|
|
||||||
// restrictions on a type parameter.
|
// restrictions on a type parameter.
|
||||||
//
|
//
|
||||||
// An external version of these APIs is available in the
|
// An external version of these APIs is available in the
|
||||||
@ -23,7 +13,6 @@
|
|||||||
package typeparams
|
package typeparams
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
@ -42,7 +31,7 @@ func UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Ex
|
|||||||
switch e := n.(type) {
|
switch e := n.(type) {
|
||||||
case *ast.IndexExpr:
|
case *ast.IndexExpr:
|
||||||
return e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack
|
return e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack
|
||||||
case *IndexListExpr:
|
case *ast.IndexListExpr:
|
||||||
return e.X, e.Lbrack, e.Indices, e.Rbrack
|
return e.X, e.Lbrack, e.Indices, e.Rbrack
|
||||||
}
|
}
|
||||||
return nil, token.NoPos, nil, token.NoPos
|
return nil, token.NoPos, nil, token.NoPos
|
||||||
@ -63,7 +52,7 @@ func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack toke
|
|||||||
Rbrack: rbrack,
|
Rbrack: rbrack,
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return &IndexListExpr{
|
return &ast.IndexListExpr{
|
||||||
X: x,
|
X: x,
|
||||||
Lbrack: lbrack,
|
Lbrack: lbrack,
|
||||||
Indices: indices,
|
Indices: indices,
|
||||||
@ -72,73 +61,17 @@ func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack toke
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTypeParam reports whether t is a type parameter.
|
// IsTypeParam reports whether t is a type parameter (or an alias of one).
|
||||||
func IsTypeParam(t types.Type) bool {
|
func IsTypeParam(t types.Type) bool {
|
||||||
_, ok := t.(*TypeParam)
|
_, ok := types.Unalias(t).(*types.TypeParam)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// OriginMethod returns the origin method associated with the method fn.
|
|
||||||
// For methods on a non-generic receiver base type, this is just
|
|
||||||
// fn. However, for methods with a generic receiver, OriginMethod returns the
|
|
||||||
// corresponding method in the method set of the origin type.
|
|
||||||
//
|
|
||||||
// As a special case, if fn is not a method (has no receiver), OriginMethod
|
|
||||||
// returns fn.
|
|
||||||
func OriginMethod(fn *types.Func) *types.Func {
|
|
||||||
recv := fn.Type().(*types.Signature).Recv()
|
|
||||||
if recv == nil {
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
base := recv.Type()
|
|
||||||
p, isPtr := base.(*types.Pointer)
|
|
||||||
if isPtr {
|
|
||||||
base = p.Elem()
|
|
||||||
}
|
|
||||||
named, isNamed := base.(*types.Named)
|
|
||||||
if !isNamed {
|
|
||||||
// Receiver is a *types.Interface.
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
if ForNamed(named).Len() == 0 {
|
|
||||||
// Receiver base has no type parameters, so we can avoid the lookup below.
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
orig := NamedTypeOrigin(named)
|
|
||||||
gfn, _, _ := types.LookupFieldOrMethod(orig, true, fn.Pkg(), fn.Name())
|
|
||||||
|
|
||||||
// This is a fix for a gopls crash (#60628) due to a go/types bug (#60634). In:
|
|
||||||
// package p
|
|
||||||
// type T *int
|
|
||||||
// func (*T) f() {}
|
|
||||||
// LookupFieldOrMethod(T, true, p, f)=nil, but NewMethodSet(*T)={(*T).f}.
|
|
||||||
// Here we make them consistent by force.
|
|
||||||
// (The go/types bug is general, but this workaround is reached only
|
|
||||||
// for generic T thanks to the early return above.)
|
|
||||||
if gfn == nil {
|
|
||||||
mset := types.NewMethodSet(types.NewPointer(orig))
|
|
||||||
for i := 0; i < mset.Len(); i++ {
|
|
||||||
m := mset.At(i)
|
|
||||||
if m.Obj().Id() == fn.Id() {
|
|
||||||
gfn = m.Obj()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In golang/go#61196, we observe another crash, this time inexplicable.
|
|
||||||
if gfn == nil {
|
|
||||||
panic(fmt.Sprintf("missing origin method for %s.%s; named == origin: %t, named.NumMethods(): %d, origin.NumMethods(): %d", named, fn, named == orig, named.NumMethods(), orig.NumMethods()))
|
|
||||||
}
|
|
||||||
|
|
||||||
return gfn.(*types.Func)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenericAssignableTo is a generalization of types.AssignableTo that
|
// GenericAssignableTo is a generalization of types.AssignableTo that
|
||||||
// implements the following rule for uninstantiated generic types:
|
// implements the following rule for uninstantiated generic types:
|
||||||
//
|
//
|
||||||
// If V and T are generic named types, then V is considered assignable to T if,
|
// If V and T are generic named types, then V is considered assignable to T if,
|
||||||
// for every possible instantation of V[A_1, ..., A_N], the instantiation
|
// for every possible instantiation of V[A_1, ..., A_N], the instantiation
|
||||||
// T[A_1, ..., A_N] is valid and V[A_1, ..., A_N] implements T[A_1, ..., A_N].
|
// T[A_1, ..., A_N] is valid and V[A_1, ..., A_N] implements T[A_1, ..., A_N].
|
||||||
//
|
//
|
||||||
// If T has structural constraints, they must be satisfied by V.
|
// If T has structural constraints, they must be satisfied by V.
|
||||||
@ -157,7 +90,10 @@ func OriginMethod(fn *types.Func) *types.Func {
|
|||||||
//
|
//
|
||||||
// In this case, GenericAssignableTo reports that instantiations of Container
|
// In this case, GenericAssignableTo reports that instantiations of Container
|
||||||
// are assignable to the corresponding instantiation of Interface.
|
// are assignable to the corresponding instantiation of Interface.
|
||||||
func GenericAssignableTo(ctxt *Context, V, T types.Type) bool {
|
func GenericAssignableTo(ctxt *types.Context, V, T types.Type) bool {
|
||||||
|
V = types.Unalias(V)
|
||||||
|
T = types.Unalias(T)
|
||||||
|
|
||||||
// If V and T are not both named, or do not have matching non-empty type
|
// If V and T are not both named, or do not have matching non-empty type
|
||||||
// parameter lists, fall back on types.AssignableTo.
|
// parameter lists, fall back on types.AssignableTo.
|
||||||
|
|
||||||
@ -167,9 +103,9 @@ func GenericAssignableTo(ctxt *Context, V, T types.Type) bool {
|
|||||||
return types.AssignableTo(V, T)
|
return types.AssignableTo(V, T)
|
||||||
}
|
}
|
||||||
|
|
||||||
vtparams := ForNamed(VN)
|
vtparams := VN.TypeParams()
|
||||||
ttparams := ForNamed(TN)
|
ttparams := TN.TypeParams()
|
||||||
if vtparams.Len() == 0 || vtparams.Len() != ttparams.Len() || NamedTypeArgs(VN).Len() != 0 || NamedTypeArgs(TN).Len() != 0 {
|
if vtparams.Len() == 0 || vtparams.Len() != ttparams.Len() || VN.TypeArgs().Len() != 0 || TN.TypeArgs().Len() != 0 {
|
||||||
return types.AssignableTo(V, T)
|
return types.AssignableTo(V, T)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +118,7 @@ func GenericAssignableTo(ctxt *Context, V, T types.Type) bool {
|
|||||||
// Minor optimization: ensure we share a context across the two
|
// Minor optimization: ensure we share a context across the two
|
||||||
// instantiations below.
|
// instantiations below.
|
||||||
if ctxt == nil {
|
if ctxt == nil {
|
||||||
ctxt = NewContext()
|
ctxt = types.NewContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
var targs []types.Type
|
var targs []types.Type
|
||||||
@ -190,12 +126,12 @@ func GenericAssignableTo(ctxt *Context, V, T types.Type) bool {
|
|||||||
targs = append(targs, vtparams.At(i))
|
targs = append(targs, vtparams.At(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
vinst, err := Instantiate(ctxt, V, targs, true)
|
vinst, err := types.Instantiate(ctxt, V, targs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("type parameters should satisfy their own constraints")
|
panic("type parameters should satisfy their own constraints")
|
||||||
}
|
}
|
||||||
|
|
||||||
tinst, err := Instantiate(ctxt, T, targs, true)
|
tinst, err := types.Instantiate(ctxt, T, targs, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
50
vendor/golang.org/x/tools/internal/typeparams/coretype.go
generated
vendored
50
vendor/golang.org/x/tools/internal/typeparams/coretype.go
generated
vendored
@ -5,6 +5,7 @@
|
|||||||
package typeparams
|
package typeparams
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"go/types"
|
"go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ func CoreType(T types.Type) types.Type {
|
|||||||
return U // for non-interface types,
|
return U // for non-interface types,
|
||||||
}
|
}
|
||||||
|
|
||||||
terms, err := _NormalTerms(U)
|
terms, err := NormalTerms(U)
|
||||||
if len(terms) == 0 || err != nil {
|
if len(terms) == 0 || err != nil {
|
||||||
// len(terms) -> empty type set of interface.
|
// len(terms) -> empty type set of interface.
|
||||||
// err != nil => U is invalid, exceeds complexity bounds, or has an empty type set.
|
// err != nil => U is invalid, exceeds complexity bounds, or has an empty type set.
|
||||||
@ -63,7 +64,7 @@ func CoreType(T types.Type) types.Type {
|
|||||||
return ch
|
return ch
|
||||||
}
|
}
|
||||||
|
|
||||||
// _NormalTerms returns a slice of terms representing the normalized structural
|
// NormalTerms returns a slice of terms representing the normalized structural
|
||||||
// type restrictions of a type, if any.
|
// type restrictions of a type, if any.
|
||||||
//
|
//
|
||||||
// For all types other than *types.TypeParam, *types.Interface, and
|
// For all types other than *types.TypeParam, *types.Interface, and
|
||||||
@ -93,30 +94,57 @@ func CoreType(T types.Type) types.Type {
|
|||||||
// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
|
// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
|
||||||
// which when intersected with C (~string|~int) yields ~string|int.
|
// which when intersected with C (~string|~int) yields ~string|int.
|
||||||
//
|
//
|
||||||
// _NormalTerms computes these expansions and reductions, producing a
|
// NormalTerms computes these expansions and reductions, producing a
|
||||||
// "normalized" form of the embeddings. A structural restriction is normalized
|
// "normalized" form of the embeddings. A structural restriction is normalized
|
||||||
// if it is a single union containing no interface terms, and is minimal in the
|
// if it is a single union containing no interface terms, and is minimal in the
|
||||||
// sense that removing any term changes the set of types satisfying the
|
// sense that removing any term changes the set of types satisfying the
|
||||||
// constraint. It is left as a proof for the reader that, modulo sorting, there
|
// constraint. It is left as a proof for the reader that, modulo sorting, there
|
||||||
// is exactly one such normalized form.
|
// is exactly one such normalized form.
|
||||||
//
|
//
|
||||||
// Because the minimal representation always takes this form, _NormalTerms
|
// Because the minimal representation always takes this form, NormalTerms
|
||||||
// returns a slice of tilde terms corresponding to the terms of the union in
|
// returns a slice of tilde terms corresponding to the terms of the union in
|
||||||
// the normalized structural restriction. An error is returned if the type is
|
// the normalized structural restriction. An error is returned if the type is
|
||||||
// invalid, exceeds complexity bounds, or has an empty type set. In the latter
|
// invalid, exceeds complexity bounds, or has an empty type set. In the latter
|
||||||
// case, _NormalTerms returns ErrEmptyTypeSet.
|
// case, NormalTerms returns ErrEmptyTypeSet.
|
||||||
//
|
//
|
||||||
// _NormalTerms makes no guarantees about the order of terms, except that it
|
// NormalTerms makes no guarantees about the order of terms, except that it
|
||||||
// is deterministic.
|
// is deterministic.
|
||||||
func _NormalTerms(typ types.Type) ([]*Term, error) {
|
func NormalTerms(typ types.Type) ([]*types.Term, error) {
|
||||||
switch typ := typ.(type) {
|
switch typ := typ.Underlying().(type) {
|
||||||
case *TypeParam:
|
case *types.TypeParam:
|
||||||
return StructuralTerms(typ)
|
return StructuralTerms(typ)
|
||||||
case *Union:
|
case *types.Union:
|
||||||
return UnionTermSet(typ)
|
return UnionTermSet(typ)
|
||||||
case *types.Interface:
|
case *types.Interface:
|
||||||
return InterfaceTermSet(typ)
|
return InterfaceTermSet(typ)
|
||||||
default:
|
default:
|
||||||
return []*Term{NewTerm(false, typ)}, nil
|
return []*types.Term{types.NewTerm(false, typ)}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deref returns the type of the variable pointed to by t,
|
||||||
|
// if t's core type is a pointer; otherwise it returns t.
|
||||||
|
//
|
||||||
|
// Do not assume that Deref(T)==T implies T is not a pointer:
|
||||||
|
// consider "type T *T", for example.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): ideally this would live in typesinternal, but that
|
||||||
|
// creates an import cycle. Move there when we melt this package down.
|
||||||
|
func Deref(t types.Type) types.Type {
|
||||||
|
if ptr, ok := CoreType(t).(*types.Pointer); ok {
|
||||||
|
return ptr.Elem()
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustDeref returns the type of the variable pointed to by t.
|
||||||
|
// It panics if t's core type is not a pointer.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): ideally this would live in typesinternal, but that
|
||||||
|
// creates an import cycle. Move there when we melt this package down.
|
||||||
|
func MustDeref(t types.Type) types.Type {
|
||||||
|
if ptr, ok := CoreType(t).(*types.Pointer); ok {
|
||||||
|
return ptr.Elem()
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("%v is not a pointer", t))
|
||||||
|
}
|
||||||
|
12
vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go
generated
vendored
12
vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
// Copyright 2021 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.18
|
|
||||||
// +build !go1.18
|
|
||||||
|
|
||||||
package typeparams
|
|
||||||
|
|
||||||
// Enabled reports whether type parameters are enabled in the current build
|
|
||||||
// environment.
|
|
||||||
const Enabled = false
|
|
15
vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go
generated
vendored
15
vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go
generated
vendored
@ -1,15 +0,0 @@
|
|||||||
// Copyright 2021 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.18
|
|
||||||
// +build go1.18
|
|
||||||
|
|
||||||
package typeparams
|
|
||||||
|
|
||||||
// Note: this constant is in a separate file as this is the only acceptable
|
|
||||||
// diff between the <1.18 API of this package and the 1.18 API.
|
|
||||||
|
|
||||||
// Enabled reports whether type parameters are enabled in the current build
|
|
||||||
// environment.
|
|
||||||
const Enabled = true
|
|
118
vendor/golang.org/x/tools/internal/typeparams/free.go
generated
vendored
Normal file
118
vendor/golang.org/x/tools/internal/typeparams/free.go
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package typeparams
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Free is a memoization of the set of free type parameters within a
|
||||||
|
// type. It makes a sequence of calls to [Free.Has] for overlapping
|
||||||
|
// types more efficient. The zero value is ready for use.
|
||||||
|
//
|
||||||
|
// NOTE: Adapted from go/types/infer.go. If it is later exported, factor.
|
||||||
|
type Free struct {
|
||||||
|
seen map[types.Type]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has reports whether the specified type has a free type parameter.
|
||||||
|
func (w *Free) Has(typ types.Type) (res bool) {
|
||||||
|
// detect cycles
|
||||||
|
if x, ok := w.seen[typ]; ok {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
if w.seen == nil {
|
||||||
|
w.seen = make(map[types.Type]bool)
|
||||||
|
}
|
||||||
|
w.seen[typ] = false
|
||||||
|
defer func() {
|
||||||
|
w.seen[typ] = res
|
||||||
|
}()
|
||||||
|
|
||||||
|
switch t := typ.(type) {
|
||||||
|
case nil, *types.Basic: // TODO(gri) should nil be handled here?
|
||||||
|
break
|
||||||
|
|
||||||
|
case *types.Alias:
|
||||||
|
return w.Has(types.Unalias(t))
|
||||||
|
|
||||||
|
case *types.Array:
|
||||||
|
return w.Has(t.Elem())
|
||||||
|
|
||||||
|
case *types.Slice:
|
||||||
|
return w.Has(t.Elem())
|
||||||
|
|
||||||
|
case *types.Struct:
|
||||||
|
for i, n := 0, t.NumFields(); i < n; i++ {
|
||||||
|
if w.Has(t.Field(i).Type()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Pointer:
|
||||||
|
return w.Has(t.Elem())
|
||||||
|
|
||||||
|
case *types.Tuple:
|
||||||
|
n := t.Len()
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
if w.Has(t.At(i).Type()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Signature:
|
||||||
|
// t.tparams may not be nil if we are looking at a signature
|
||||||
|
// of a generic function type (or an interface method) that is
|
||||||
|
// part of the type we're testing. We don't care about these type
|
||||||
|
// parameters.
|
||||||
|
// Similarly, the receiver of a method may declare (rather than
|
||||||
|
// use) type parameters, we don't care about those either.
|
||||||
|
// Thus, we only need to look at the input and result parameters.
|
||||||
|
return w.Has(t.Params()) || w.Has(t.Results())
|
||||||
|
|
||||||
|
case *types.Interface:
|
||||||
|
for i, n := 0, t.NumMethods(); i < n; i++ {
|
||||||
|
if w.Has(t.Method(i).Type()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
terms, err := InterfaceTermSet(t)
|
||||||
|
if err != nil {
|
||||||
|
return false // ill typed
|
||||||
|
}
|
||||||
|
for _, term := range terms {
|
||||||
|
if w.Has(term.Type()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Map:
|
||||||
|
return w.Has(t.Key()) || w.Has(t.Elem())
|
||||||
|
|
||||||
|
case *types.Chan:
|
||||||
|
return w.Has(t.Elem())
|
||||||
|
|
||||||
|
case *types.Named:
|
||||||
|
args := t.TypeArgs()
|
||||||
|
// TODO(taking): this does not match go/types/infer.go. Check with rfindley.
|
||||||
|
if params := t.TypeParams(); params.Len() > args.Len() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for i, n := 0, args.Len(); i < n; i++ {
|
||||||
|
if w.Has(args.At(i)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return w.Has(t.Underlying()) // recurse for types local to parameterized functions
|
||||||
|
|
||||||
|
case *types.TypeParam:
|
||||||
|
return true
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(t) // unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
20
vendor/golang.org/x/tools/internal/typeparams/normalize.go
generated
vendored
20
vendor/golang.org/x/tools/internal/typeparams/normalize.go
generated
vendored
@ -60,7 +60,7 @@ var ErrEmptyTypeSet = errors.New("empty type set")
|
|||||||
//
|
//
|
||||||
// StructuralTerms makes no guarantees about the order of terms, except that it
|
// StructuralTerms makes no guarantees about the order of terms, except that it
|
||||||
// is deterministic.
|
// is deterministic.
|
||||||
func StructuralTerms(tparam *TypeParam) ([]*Term, error) {
|
func StructuralTerms(tparam *types.TypeParam) ([]*types.Term, error) {
|
||||||
constraint := tparam.Constraint()
|
constraint := tparam.Constraint()
|
||||||
if constraint == nil {
|
if constraint == nil {
|
||||||
return nil, fmt.Errorf("%s has nil constraint", tparam)
|
return nil, fmt.Errorf("%s has nil constraint", tparam)
|
||||||
@ -78,7 +78,7 @@ func StructuralTerms(tparam *TypeParam) ([]*Term, error) {
|
|||||||
//
|
//
|
||||||
// See the documentation of StructuralTerms for more information on
|
// See the documentation of StructuralTerms for more information on
|
||||||
// normalization.
|
// normalization.
|
||||||
func InterfaceTermSet(iface *types.Interface) ([]*Term, error) {
|
func InterfaceTermSet(iface *types.Interface) ([]*types.Term, error) {
|
||||||
return computeTermSet(iface)
|
return computeTermSet(iface)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,11 +88,11 @@ func InterfaceTermSet(iface *types.Interface) ([]*Term, error) {
|
|||||||
//
|
//
|
||||||
// See the documentation of StructuralTerms for more information on
|
// See the documentation of StructuralTerms for more information on
|
||||||
// normalization.
|
// normalization.
|
||||||
func UnionTermSet(union *Union) ([]*Term, error) {
|
func UnionTermSet(union *types.Union) ([]*types.Term, error) {
|
||||||
return computeTermSet(union)
|
return computeTermSet(union)
|
||||||
}
|
}
|
||||||
|
|
||||||
func computeTermSet(typ types.Type) ([]*Term, error) {
|
func computeTermSet(typ types.Type) ([]*types.Term, error) {
|
||||||
tset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0)
|
tset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -103,9 +103,9 @@ func computeTermSet(typ types.Type) ([]*Term, error) {
|
|||||||
if tset.terms.isAll() {
|
if tset.terms.isAll() {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
var terms []*Term
|
var terms []*types.Term
|
||||||
for _, term := range tset.terms {
|
for _, term := range tset.terms {
|
||||||
terms = append(terms, NewTerm(term.tilde, term.typ))
|
terms = append(terms, types.NewTerm(term.tilde, term.typ))
|
||||||
}
|
}
|
||||||
return terms, nil
|
return terms, nil
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in
|
|||||||
tset.terms = allTermlist
|
tset.terms = allTermlist
|
||||||
for i := 0; i < u.NumEmbeddeds(); i++ {
|
for i := 0; i < u.NumEmbeddeds(); i++ {
|
||||||
embedded := u.EmbeddedType(i)
|
embedded := u.EmbeddedType(i)
|
||||||
if _, ok := embedded.Underlying().(*TypeParam); ok {
|
if _, ok := embedded.Underlying().(*types.TypeParam); ok {
|
||||||
return nil, fmt.Errorf("invalid embedded type %T", embedded)
|
return nil, fmt.Errorf("invalid embedded type %T", embedded)
|
||||||
}
|
}
|
||||||
tset2, err := computeTermSetInternal(embedded, seen, depth+1)
|
tset2, err := computeTermSetInternal(embedded, seen, depth+1)
|
||||||
@ -171,7 +171,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in
|
|||||||
}
|
}
|
||||||
tset.terms = tset.terms.intersect(tset2.terms)
|
tset.terms = tset.terms.intersect(tset2.terms)
|
||||||
}
|
}
|
||||||
case *Union:
|
case *types.Union:
|
||||||
// The term set of a union is the union of term sets of its terms.
|
// The term set of a union is the union of term sets of its terms.
|
||||||
tset.terms = nil
|
tset.terms = nil
|
||||||
for i := 0; i < u.Len(); i++ {
|
for i := 0; i < u.Len(); i++ {
|
||||||
@ -184,7 +184,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
terms = tset2.terms
|
terms = tset2.terms
|
||||||
case *TypeParam, *Union:
|
case *types.TypeParam, *types.Union:
|
||||||
// A stand-alone type parameter or union is not permitted as union
|
// A stand-alone type parameter or union is not permitted as union
|
||||||
// term.
|
// term.
|
||||||
return nil, fmt.Errorf("invalid union term %T", t)
|
return nil, fmt.Errorf("invalid union term %T", t)
|
||||||
@ -199,7 +199,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in
|
|||||||
return nil, fmt.Errorf("exceeded max term count %d", maxTermCount)
|
return nil, fmt.Errorf("exceeded max term count %d", maxTermCount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *TypeParam:
|
case *types.TypeParam:
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
default:
|
default:
|
||||||
// For all other types, the term set is just a single non-tilde term
|
// For all other types, the term set is just a single non-tilde term
|
||||||
|
197
vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go
generated
vendored
197
vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go
generated
vendored
@ -1,197 +0,0 @@
|
|||||||
// Copyright 2021 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.18
|
|
||||||
// +build !go1.18
|
|
||||||
|
|
||||||
package typeparams
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/ast"
|
|
||||||
"go/token"
|
|
||||||
"go/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func unsupported() {
|
|
||||||
panic("type parameters are unsupported at this go version")
|
|
||||||
}
|
|
||||||
|
|
||||||
// IndexListExpr is a placeholder type, as type parameters are not supported at
|
|
||||||
// this Go version. Its methods panic on use.
|
|
||||||
type IndexListExpr struct {
|
|
||||||
ast.Expr
|
|
||||||
X ast.Expr // expression
|
|
||||||
Lbrack token.Pos // position of "["
|
|
||||||
Indices []ast.Expr // index expressions
|
|
||||||
Rbrack token.Pos // position of "]"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForTypeSpec returns an empty field list, as type parameters on not supported
|
|
||||||
// at this Go version.
|
|
||||||
func ForTypeSpec(*ast.TypeSpec) *ast.FieldList {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForFuncType returns an empty field list, as type parameters are not
|
|
||||||
// supported at this Go version.
|
|
||||||
func ForFuncType(*ast.FuncType) *ast.FieldList {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TypeParam is a placeholder type, as type parameters are not supported at
|
|
||||||
// this Go version. Its methods panic on use.
|
|
||||||
type TypeParam struct{ types.Type }
|
|
||||||
|
|
||||||
func (*TypeParam) Index() int { unsupported(); return 0 }
|
|
||||||
func (*TypeParam) Constraint() types.Type { unsupported(); return nil }
|
|
||||||
func (*TypeParam) Obj() *types.TypeName { unsupported(); return nil }
|
|
||||||
|
|
||||||
// TypeParamList is a placeholder for an empty type parameter list.
|
|
||||||
type TypeParamList struct{}
|
|
||||||
|
|
||||||
func (*TypeParamList) Len() int { return 0 }
|
|
||||||
func (*TypeParamList) At(int) *TypeParam { unsupported(); return nil }
|
|
||||||
|
|
||||||
// TypeList is a placeholder for an empty type list.
|
|
||||||
type TypeList struct{}
|
|
||||||
|
|
||||||
func (*TypeList) Len() int { return 0 }
|
|
||||||
func (*TypeList) At(int) types.Type { unsupported(); return nil }
|
|
||||||
|
|
||||||
// NewTypeParam is unsupported at this Go version, and panics.
|
|
||||||
func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam {
|
|
||||||
unsupported()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTypeParamConstraint is unsupported at this Go version, and panics.
|
|
||||||
func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) {
|
|
||||||
unsupported()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSignatureType calls types.NewSignature, panicking if recvTypeParams or
|
|
||||||
// typeParams is non-empty.
|
|
||||||
func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature {
|
|
||||||
if len(recvTypeParams) != 0 || len(typeParams) != 0 {
|
|
||||||
panic("signatures cannot have type parameters at this Go version")
|
|
||||||
}
|
|
||||||
return types.NewSignature(recv, params, results, variadic)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForSignature returns an empty slice.
|
|
||||||
func ForSignature(*types.Signature) *TypeParamList {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RecvTypeParams returns a nil slice.
|
|
||||||
func RecvTypeParams(sig *types.Signature) *TypeParamList {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsComparable returns false, as no interfaces are type-restricted at this Go
|
|
||||||
// version.
|
|
||||||
func IsComparable(*types.Interface) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsMethodSet returns true, as no interfaces are type-restricted at this Go
|
|
||||||
// version.
|
|
||||||
func IsMethodSet(*types.Interface) bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsImplicit returns false, as no interfaces are implicit at this Go version.
|
|
||||||
func IsImplicit(*types.Interface) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarkImplicit does nothing, because this Go version does not have implicit
|
|
||||||
// interfaces.
|
|
||||||
func MarkImplicit(*types.Interface) {}
|
|
||||||
|
|
||||||
// ForNamed returns an empty type parameter list, as type parameters are not
|
|
||||||
// supported at this Go version.
|
|
||||||
func ForNamed(*types.Named) *TypeParamList {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetForNamed panics if tparams is non-empty.
|
|
||||||
func SetForNamed(_ *types.Named, tparams []*TypeParam) {
|
|
||||||
if len(tparams) > 0 {
|
|
||||||
unsupported()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NamedTypeArgs returns nil.
|
|
||||||
func NamedTypeArgs(*types.Named) *TypeList {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NamedTypeOrigin is the identity method at this Go version.
|
|
||||||
func NamedTypeOrigin(named *types.Named) *types.Named {
|
|
||||||
return named
|
|
||||||
}
|
|
||||||
|
|
||||||
// Term holds information about a structural type restriction.
|
|
||||||
type Term struct {
|
|
||||||
tilde bool
|
|
||||||
typ types.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Term) Tilde() bool { return m.tilde }
|
|
||||||
func (m *Term) Type() types.Type { return m.typ }
|
|
||||||
func (m *Term) String() string {
|
|
||||||
pre := ""
|
|
||||||
if m.tilde {
|
|
||||||
pre = "~"
|
|
||||||
}
|
|
||||||
return pre + m.typ.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTerm is unsupported at this Go version, and panics.
|
|
||||||
func NewTerm(tilde bool, typ types.Type) *Term {
|
|
||||||
return &Term{tilde, typ}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Union is a placeholder type, as type parameters are not supported at this Go
|
|
||||||
// version. Its methods panic on use.
|
|
||||||
type Union struct{ types.Type }
|
|
||||||
|
|
||||||
func (*Union) Len() int { return 0 }
|
|
||||||
func (*Union) Term(i int) *Term { unsupported(); return nil }
|
|
||||||
|
|
||||||
// NewUnion is unsupported at this Go version, and panics.
|
|
||||||
func NewUnion(terms []*Term) *Union {
|
|
||||||
unsupported()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitInstanceInfo is a noop at this Go version.
|
|
||||||
func InitInstanceInfo(*types.Info) {}
|
|
||||||
|
|
||||||
// Instance is a placeholder type, as type parameters are not supported at this
|
|
||||||
// Go version.
|
|
||||||
type Instance struct {
|
|
||||||
TypeArgs *TypeList
|
|
||||||
Type types.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetInstances returns a nil map, as type parameters are not supported at this
|
|
||||||
// Go version.
|
|
||||||
func GetInstances(info *types.Info) map[*ast.Ident]Instance { return nil }
|
|
||||||
|
|
||||||
// Context is a placeholder type, as type parameters are not supported at
|
|
||||||
// this Go version.
|
|
||||||
type Context struct{}
|
|
||||||
|
|
||||||
// NewContext returns a placeholder Context instance.
|
|
||||||
func NewContext() *Context {
|
|
||||||
return &Context{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instantiate is unsupported on this Go version, and panics.
|
|
||||||
func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
|
|
||||||
unsupported()
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
151
vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go
generated
vendored
151
vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go
generated
vendored
@ -1,151 +0,0 @@
|
|||||||
// Copyright 2021 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.18
|
|
||||||
// +build go1.18
|
|
||||||
|
|
||||||
package typeparams
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/ast"
|
|
||||||
"go/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IndexListExpr is an alias for ast.IndexListExpr.
|
|
||||||
type IndexListExpr = ast.IndexListExpr
|
|
||||||
|
|
||||||
// ForTypeSpec returns n.TypeParams.
|
|
||||||
func ForTypeSpec(n *ast.TypeSpec) *ast.FieldList {
|
|
||||||
if n == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return n.TypeParams
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForFuncType returns n.TypeParams.
|
|
||||||
func ForFuncType(n *ast.FuncType) *ast.FieldList {
|
|
||||||
if n == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return n.TypeParams
|
|
||||||
}
|
|
||||||
|
|
||||||
// TypeParam is an alias for types.TypeParam
|
|
||||||
type TypeParam = types.TypeParam
|
|
||||||
|
|
||||||
// TypeParamList is an alias for types.TypeParamList
|
|
||||||
type TypeParamList = types.TypeParamList
|
|
||||||
|
|
||||||
// TypeList is an alias for types.TypeList
|
|
||||||
type TypeList = types.TypeList
|
|
||||||
|
|
||||||
// NewTypeParam calls types.NewTypeParam.
|
|
||||||
func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam {
|
|
||||||
return types.NewTypeParam(name, constraint)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTypeParamConstraint calls tparam.SetConstraint(constraint).
|
|
||||||
func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) {
|
|
||||||
tparam.SetConstraint(constraint)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSignatureType calls types.NewSignatureType.
|
|
||||||
func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature {
|
|
||||||
return types.NewSignatureType(recv, recvTypeParams, typeParams, params, results, variadic)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForSignature returns sig.TypeParams()
|
|
||||||
func ForSignature(sig *types.Signature) *TypeParamList {
|
|
||||||
return sig.TypeParams()
|
|
||||||
}
|
|
||||||
|
|
||||||
// RecvTypeParams returns sig.RecvTypeParams().
|
|
||||||
func RecvTypeParams(sig *types.Signature) *TypeParamList {
|
|
||||||
return sig.RecvTypeParams()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsComparable calls iface.IsComparable().
|
|
||||||
func IsComparable(iface *types.Interface) bool {
|
|
||||||
return iface.IsComparable()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsMethodSet calls iface.IsMethodSet().
|
|
||||||
func IsMethodSet(iface *types.Interface) bool {
|
|
||||||
return iface.IsMethodSet()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsImplicit calls iface.IsImplicit().
|
|
||||||
func IsImplicit(iface *types.Interface) bool {
|
|
||||||
return iface.IsImplicit()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarkImplicit calls iface.MarkImplicit().
|
|
||||||
func MarkImplicit(iface *types.Interface) {
|
|
||||||
iface.MarkImplicit()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForNamed extracts the (possibly empty) type parameter object list from
|
|
||||||
// named.
|
|
||||||
func ForNamed(named *types.Named) *TypeParamList {
|
|
||||||
return named.TypeParams()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetForNamed sets the type params tparams on n. Each tparam must be of
|
|
||||||
// dynamic type *types.TypeParam.
|
|
||||||
func SetForNamed(n *types.Named, tparams []*TypeParam) {
|
|
||||||
n.SetTypeParams(tparams)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NamedTypeArgs returns named.TypeArgs().
|
|
||||||
func NamedTypeArgs(named *types.Named) *TypeList {
|
|
||||||
return named.TypeArgs()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NamedTypeOrigin returns named.Orig().
|
|
||||||
func NamedTypeOrigin(named *types.Named) *types.Named {
|
|
||||||
return named.Origin()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Term is an alias for types.Term.
|
|
||||||
type Term = types.Term
|
|
||||||
|
|
||||||
// NewTerm calls types.NewTerm.
|
|
||||||
func NewTerm(tilde bool, typ types.Type) *Term {
|
|
||||||
return types.NewTerm(tilde, typ)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Union is an alias for types.Union
|
|
||||||
type Union = types.Union
|
|
||||||
|
|
||||||
// NewUnion calls types.NewUnion.
|
|
||||||
func NewUnion(terms []*Term) *Union {
|
|
||||||
return types.NewUnion(terms)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitInstanceInfo initializes info to record information about type and
|
|
||||||
// function instances.
|
|
||||||
func InitInstanceInfo(info *types.Info) {
|
|
||||||
info.Instances = make(map[*ast.Ident]types.Instance)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instance is an alias for types.Instance.
|
|
||||||
type Instance = types.Instance
|
|
||||||
|
|
||||||
// GetInstances returns info.Instances.
|
|
||||||
func GetInstances(info *types.Info) map[*ast.Ident]Instance {
|
|
||||||
return info.Instances
|
|
||||||
}
|
|
||||||
|
|
||||||
// Context is an alias for types.Context.
|
|
||||||
type Context = types.Context
|
|
||||||
|
|
||||||
// NewContext calls types.NewContext.
|
|
||||||
func NewContext() *Context {
|
|
||||||
return types.NewContext()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instantiate calls types.Instantiate.
|
|
||||||
func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
|
|
||||||
return types.Instantiate(ctxt, typ, targs, validate)
|
|
||||||
}
|
|
133
vendor/golang.org/x/tools/internal/typesinternal/element.go
generated
vendored
Normal file
133
vendor/golang.org/x/tools/internal/typesinternal/element.go
generated
vendored
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package typesinternal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ForEachElement calls f for type T and each type reachable from its
|
||||||
|
// type through reflection. It does this by recursively stripping off
|
||||||
|
// type constructors; in addition, for each named type N, the type *N
|
||||||
|
// is added to the result as it may have additional methods.
|
||||||
|
//
|
||||||
|
// The caller must provide an initially empty set used to de-duplicate
|
||||||
|
// identical types, potentially across multiple calls to ForEachElement.
|
||||||
|
// (Its final value holds all the elements seen, matching the arguments
|
||||||
|
// passed to f.)
|
||||||
|
//
|
||||||
|
// TODO(adonovan): share/harmonize with go/callgraph/rta.
|
||||||
|
func ForEachElement(rtypes *typeutil.Map, msets *typeutil.MethodSetCache, T types.Type, f func(types.Type)) {
|
||||||
|
var visit func(T types.Type, skip bool)
|
||||||
|
visit = func(T types.Type, skip bool) {
|
||||||
|
if !skip {
|
||||||
|
if seen, _ := rtypes.Set(T, true).(bool); seen {
|
||||||
|
return // de-dup
|
||||||
|
}
|
||||||
|
|
||||||
|
f(T) // notify caller of new element type
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursion over signatures of each method.
|
||||||
|
tmset := msets.MethodSet(T)
|
||||||
|
for i := 0; i < tmset.Len(); i++ {
|
||||||
|
sig := tmset.At(i).Type().(*types.Signature)
|
||||||
|
// It is tempting to call visit(sig, false)
|
||||||
|
// but, as noted in golang.org/cl/65450043,
|
||||||
|
// the Signature.Recv field is ignored by
|
||||||
|
// types.Identical and typeutil.Map, which
|
||||||
|
// is confusing at best.
|
||||||
|
//
|
||||||
|
// More importantly, the true signature rtype
|
||||||
|
// reachable from a method using reflection
|
||||||
|
// has no receiver but an extra ordinary parameter.
|
||||||
|
// For the Read method of io.Reader we want:
|
||||||
|
// func(Reader, []byte) (int, error)
|
||||||
|
// but here sig is:
|
||||||
|
// func([]byte) (int, error)
|
||||||
|
// with .Recv = Reader (though it is hard to
|
||||||
|
// notice because it doesn't affect Signature.String
|
||||||
|
// or types.Identical).
|
||||||
|
//
|
||||||
|
// TODO(adonovan): construct and visit the correct
|
||||||
|
// non-method signature with an extra parameter
|
||||||
|
// (though since unnamed func types have no methods
|
||||||
|
// there is essentially no actual demand for this).
|
||||||
|
//
|
||||||
|
// TODO(adonovan): document whether or not it is
|
||||||
|
// safe to skip non-exported methods (as RTA does).
|
||||||
|
visit(sig.Params(), true) // skip the Tuple
|
||||||
|
visit(sig.Results(), true) // skip the Tuple
|
||||||
|
}
|
||||||
|
|
||||||
|
switch T := T.(type) {
|
||||||
|
case *types.Alias:
|
||||||
|
visit(types.Unalias(T), skip) // emulates the pre-Alias behavior
|
||||||
|
|
||||||
|
case *types.Basic:
|
||||||
|
// nop
|
||||||
|
|
||||||
|
case *types.Interface:
|
||||||
|
// nop---handled by recursion over method set.
|
||||||
|
|
||||||
|
case *types.Pointer:
|
||||||
|
visit(T.Elem(), false)
|
||||||
|
|
||||||
|
case *types.Slice:
|
||||||
|
visit(T.Elem(), false)
|
||||||
|
|
||||||
|
case *types.Chan:
|
||||||
|
visit(T.Elem(), false)
|
||||||
|
|
||||||
|
case *types.Map:
|
||||||
|
visit(T.Key(), false)
|
||||||
|
visit(T.Elem(), false)
|
||||||
|
|
||||||
|
case *types.Signature:
|
||||||
|
if T.Recv() != nil {
|
||||||
|
panic(fmt.Sprintf("Signature %s has Recv %s", T, T.Recv()))
|
||||||
|
}
|
||||||
|
visit(T.Params(), true) // skip the Tuple
|
||||||
|
visit(T.Results(), true) // skip the Tuple
|
||||||
|
|
||||||
|
case *types.Named:
|
||||||
|
// A pointer-to-named type can be derived from a named
|
||||||
|
// type via reflection. It may have methods too.
|
||||||
|
visit(types.NewPointer(T), false)
|
||||||
|
|
||||||
|
// Consider 'type T struct{S}' where S has methods.
|
||||||
|
// Reflection provides no way to get from T to struct{S},
|
||||||
|
// only to S, so the method set of struct{S} is unwanted,
|
||||||
|
// so set 'skip' flag during recursion.
|
||||||
|
visit(T.Underlying(), true) // skip the unnamed type
|
||||||
|
|
||||||
|
case *types.Array:
|
||||||
|
visit(T.Elem(), false)
|
||||||
|
|
||||||
|
case *types.Struct:
|
||||||
|
for i, n := 0, T.NumFields(); i < n; i++ {
|
||||||
|
// TODO(adonovan): document whether or not
|
||||||
|
// it is safe to skip non-exported fields.
|
||||||
|
visit(T.Field(i).Type(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Tuple:
|
||||||
|
for i, n := 0, T.Len(); i < n; i++ {
|
||||||
|
visit(T.At(i).Type(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.TypeParam, *types.Union:
|
||||||
|
// forEachReachable must not be called on parameterized types.
|
||||||
|
panic(T)
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(T)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visit(T, false)
|
||||||
|
}
|
14
vendor/golang.org/x/tools/internal/typesinternal/errorcode.go
generated
vendored
14
vendor/golang.org/x/tools/internal/typesinternal/errorcode.go
generated
vendored
@ -167,7 +167,7 @@ const (
|
|||||||
UntypedNilUse
|
UntypedNilUse
|
||||||
|
|
||||||
// WrongAssignCount occurs when the number of values on the right-hand side
|
// WrongAssignCount occurs when the number of values on the right-hand side
|
||||||
// of an assignment or or initialization expression does not match the number
|
// of an assignment or initialization expression does not match the number
|
||||||
// of variables on the left-hand side.
|
// of variables on the left-hand side.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
@ -838,7 +838,7 @@ const (
|
|||||||
// InvalidCap occurs when an argument to the cap built-in function is not of
|
// InvalidCap occurs when an argument to the cap built-in function is not of
|
||||||
// supported type.
|
// supported type.
|
||||||
//
|
//
|
||||||
// See https://golang.org/ref/spec#Lengthand_capacity for information on
|
// See https://golang.org/ref/spec#Length_and_capacity for information on
|
||||||
// which underlying types are supported as arguments to cap and len.
|
// which underlying types are supported as arguments to cap and len.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
@ -859,7 +859,7 @@ const (
|
|||||||
// InvalidCopy occurs when the arguments are not of slice type or do not
|
// InvalidCopy occurs when the arguments are not of slice type or do not
|
||||||
// have compatible type.
|
// have compatible type.
|
||||||
//
|
//
|
||||||
// See https://golang.org/ref/spec#Appendingand_copying_slices for more
|
// See https://golang.org/ref/spec#Appending_and_copying_slices for more
|
||||||
// information on the type requirements for the copy built-in.
|
// information on the type requirements for the copy built-in.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
@ -897,7 +897,7 @@ const (
|
|||||||
// InvalidLen occurs when an argument to the len built-in function is not of
|
// InvalidLen occurs when an argument to the len built-in function is not of
|
||||||
// supported type.
|
// supported type.
|
||||||
//
|
//
|
||||||
// See https://golang.org/ref/spec#Lengthand_capacity for information on
|
// See https://golang.org/ref/spec#Length_and_capacity for information on
|
||||||
// which underlying types are supported as arguments to cap and len.
|
// which underlying types are supported as arguments to cap and len.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
@ -914,7 +914,7 @@ const (
|
|||||||
|
|
||||||
// InvalidMake occurs when make is called with an unsupported type argument.
|
// InvalidMake occurs when make is called with an unsupported type argument.
|
||||||
//
|
//
|
||||||
// See https://golang.org/ref/spec#Makingslices_maps_and_channels for
|
// See https://golang.org/ref/spec#Making_slices_maps_and_channels for
|
||||||
// information on the types that may be created using make.
|
// information on the types that may be created using make.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
@ -1449,10 +1449,10 @@ const (
|
|||||||
NotAGenericType
|
NotAGenericType
|
||||||
|
|
||||||
// WrongTypeArgCount occurs when a type or function is instantiated with an
|
// WrongTypeArgCount occurs when a type or function is instantiated with an
|
||||||
// incorrent number of type arguments, including when a generic type or
|
// incorrect number of type arguments, including when a generic type or
|
||||||
// function is used without instantiation.
|
// function is used without instantiation.
|
||||||
//
|
//
|
||||||
// Errors inolving failed type inference are assigned other error codes.
|
// Errors involving failed type inference are assigned other error codes.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
// type T[p any] int
|
// type T[p any] int
|
||||||
|
24
vendor/golang.org/x/tools/internal/typesinternal/objectpath.go
generated
vendored
24
vendor/golang.org/x/tools/internal/typesinternal/objectpath.go
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
// Copyright 2023 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"
|
|
||||||
|
|
||||||
// This file contains back doors that allow gopls to avoid method sorting when
|
|
||||||
// using the objectpath package.
|
|
||||||
//
|
|
||||||
// This is performance-critical in certain repositories, but changing the
|
|
||||||
// behavior of the objectpath package is still being discussed in
|
|
||||||
// golang/go#61443. If we decide to remove the sorting in objectpath we can
|
|
||||||
// simply delete these back doors. Otherwise, we should add a new API to
|
|
||||||
// objectpath that allows controlling the sorting.
|
|
||||||
|
|
||||||
// SkipEncoderMethodSorting marks enc (which must be an *objectpath.Encoder) as
|
|
||||||
// not requiring sorted methods.
|
|
||||||
var SkipEncoderMethodSorting func(enc interface{})
|
|
||||||
|
|
||||||
// ObjectpathObject is like objectpath.Object, but allows suppressing method
|
|
||||||
// sorting.
|
|
||||||
var ObjectpathObject func(pkg *types.Package, p string, skipMethodSorting bool) (types.Object, error)
|
|
41
vendor/golang.org/x/tools/internal/typesinternal/recv.go
generated
vendored
Normal file
41
vendor/golang.org/x/tools/internal/typesinternal/recv.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package typesinternal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReceiverNamed returns the named type (if any) associated with the
|
||||||
|
// type of recv, which may be of the form N or *N, or aliases thereof.
|
||||||
|
// It also reports whether a Pointer was present.
|
||||||
|
func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) {
|
||||||
|
t := recv.Type()
|
||||||
|
if ptr, ok := types.Unalias(t).(*types.Pointer); ok {
|
||||||
|
isPtr = true
|
||||||
|
t = ptr.Elem()
|
||||||
|
}
|
||||||
|
named, _ = types.Unalias(t).(*types.Named)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unpointer returns T given *T or an alias thereof.
|
||||||
|
// For all other types it is the identity function.
|
||||||
|
// It does not look at underlying types.
|
||||||
|
// The result may be an alias.
|
||||||
|
//
|
||||||
|
// Use this function to strip off the optional pointer on a receiver
|
||||||
|
// in a field or method selection, without losing the named type
|
||||||
|
// (which is needed to compute the method set).
|
||||||
|
//
|
||||||
|
// See also [typeparams.MustDeref], which removes one level of
|
||||||
|
// indirection from the type, regardless of named types (analogous to
|
||||||
|
// a LOAD instruction).
|
||||||
|
func Unpointer(t types.Type) types.Type {
|
||||||
|
if ptr, ok := types.Unalias(t).(*types.Pointer); ok {
|
||||||
|
return ptr.Elem()
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
89
vendor/golang.org/x/tools/internal/typesinternal/toonew.go
generated
vendored
Normal file
89
vendor/golang.org/x/tools/internal/typesinternal/toonew.go
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package typesinternal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/stdlib"
|
||||||
|
"golang.org/x/tools/internal/versions"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TooNewStdSymbols computes the set of package-level symbols
|
||||||
|
// exported by pkg that are not available at the specified version.
|
||||||
|
// The result maps each symbol to its minimum version.
|
||||||
|
//
|
||||||
|
// The pkg is allowed to contain type errors.
|
||||||
|
func TooNewStdSymbols(pkg *types.Package, version string) map[types.Object]string {
|
||||||
|
disallowed := make(map[types.Object]string)
|
||||||
|
|
||||||
|
// Pass 1: package-level symbols.
|
||||||
|
symbols := stdlib.PackageSymbols[pkg.Path()]
|
||||||
|
for _, sym := range symbols {
|
||||||
|
symver := sym.Version.String()
|
||||||
|
if versions.Before(version, symver) {
|
||||||
|
switch sym.Kind {
|
||||||
|
case stdlib.Func, stdlib.Var, stdlib.Const, stdlib.Type:
|
||||||
|
disallowed[pkg.Scope().Lookup(sym.Name)] = symver
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass 2: fields and methods.
|
||||||
|
//
|
||||||
|
// We allow fields and methods if their associated type is
|
||||||
|
// disallowed, as otherwise we would report false positives
|
||||||
|
// for compatibility shims. Consider:
|
||||||
|
//
|
||||||
|
// //go:build go1.22
|
||||||
|
// type T struct { F std.Real } // correct new API
|
||||||
|
//
|
||||||
|
// //go:build !go1.22
|
||||||
|
// type T struct { F fake } // shim
|
||||||
|
// type fake struct { ... }
|
||||||
|
// func (fake) M () {}
|
||||||
|
//
|
||||||
|
// These alternative declarations of T use either the std.Real
|
||||||
|
// type, introduced in go1.22, or a fake type, for the field
|
||||||
|
// F. (The fakery could be arbitrarily deep, involving more
|
||||||
|
// nested fields and methods than are shown here.) Clients
|
||||||
|
// that use the compatibility shim T will compile with any
|
||||||
|
// version of go, whether older or newer than go1.22, but only
|
||||||
|
// the newer version will use the std.Real implementation.
|
||||||
|
//
|
||||||
|
// Now consider a reference to method M in new(T).F.M() in a
|
||||||
|
// module that requires a minimum of go1.21. The analysis may
|
||||||
|
// occur using a version of Go higher than 1.21, selecting the
|
||||||
|
// first version of T, so the method M is Real.M. This would
|
||||||
|
// spuriously cause the analyzer to report a reference to a
|
||||||
|
// too-new symbol even though this expression compiles just
|
||||||
|
// fine (with the fake implementation) using go1.21.
|
||||||
|
for _, sym := range symbols {
|
||||||
|
symVersion := sym.Version.String()
|
||||||
|
if !versions.Before(version, symVersion) {
|
||||||
|
continue // allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj types.Object
|
||||||
|
switch sym.Kind {
|
||||||
|
case stdlib.Field:
|
||||||
|
typename, name := sym.SplitField()
|
||||||
|
if t := pkg.Scope().Lookup(typename); t != nil && disallowed[t] == "" {
|
||||||
|
obj, _, _ = types.LookupFieldOrMethod(t.Type(), false, pkg, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
case stdlib.Method:
|
||||||
|
ptr, recvname, name := sym.SplitMethod()
|
||||||
|
if t := pkg.Scope().Lookup(recvname); t != nil && disallowed[t] == "" {
|
||||||
|
obj, _, _ = types.LookupFieldOrMethod(t.Type(), ptr, pkg, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if obj != nil {
|
||||||
|
disallowed[obj] = symVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return disallowed
|
||||||
|
}
|
15
vendor/golang.org/x/tools/internal/typesinternal/types.go
generated
vendored
15
vendor/golang.org/x/tools/internal/typesinternal/types.go
generated
vendored
@ -49,4 +49,17 @@ func ReadGo116ErrorData(err types.Error) (code ErrorCode, start, end token.Pos,
|
|||||||
return ErrorCode(data[0]), token.Pos(data[1]), token.Pos(data[2]), true
|
return ErrorCode(data[0]), token.Pos(data[1]), token.Pos(data[2]), true
|
||||||
}
|
}
|
||||||
|
|
||||||
var SetGoVersion = func(conf *types.Config, version string) bool { return false }
|
// NameRelativeTo returns a types.Qualifier that qualifies members of
|
||||||
|
// all packages other than pkg, using only the package name.
|
||||||
|
// (By contrast, [types.RelativeTo] uses the complete package path,
|
||||||
|
// which is often excessive.)
|
||||||
|
//
|
||||||
|
// If pkg is nil, it is equivalent to [*types.Package.Name].
|
||||||
|
func NameRelativeTo(pkg *types.Package) types.Qualifier {
|
||||||
|
return func(other *types.Package) string {
|
||||||
|
if pkg != nil && pkg == other {
|
||||||
|
return "" // same package; unqualified
|
||||||
|
}
|
||||||
|
return other.Name()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
19
vendor/golang.org/x/tools/internal/typesinternal/types_118.go
generated
vendored
19
vendor/golang.org/x/tools/internal/typesinternal/types_118.go
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
// Copyright 2021 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.18
|
|
||||||
// +build go1.18
|
|
||||||
|
|
||||||
package typesinternal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
SetGoVersion = func(conf *types.Config, version string) bool {
|
|
||||||
conf.GoVersion = version
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
13
vendor/golang.org/x/tools/internal/versions/constraint.go
generated
vendored
Normal file
13
vendor/golang.org/x/tools/internal/versions/constraint.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package versions
|
||||||
|
|
||||||
|
import "go/build/constraint"
|
||||||
|
|
||||||
|
// ConstraintGoVersion is constraint.GoVersion (if built with go1.21+).
|
||||||
|
// Otherwise nil.
|
||||||
|
//
|
||||||
|
// Deprecate once x/tools is after go1.21.
|
||||||
|
var ConstraintGoVersion func(x constraint.Expr) string
|
14
vendor/golang.org/x/tools/internal/versions/constraint_go121.go
generated
vendored
Normal file
14
vendor/golang.org/x/tools/internal/versions/constraint_go121.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// 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.21
|
||||||
|
// +build go1.21
|
||||||
|
|
||||||
|
package versions
|
||||||
|
|
||||||
|
import "go/build/constraint"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ConstraintGoVersion = constraint.GoVersion
|
||||||
|
}
|
43
vendor/golang.org/x/tools/internal/versions/features.go
generated
vendored
Normal file
43
vendor/golang.org/x/tools/internal/versions/features.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2023 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 versions
|
||||||
|
|
||||||
|
// This file contains predicates for working with file versions to
|
||||||
|
// decide when a tool should consider a language feature enabled.
|
||||||
|
|
||||||
|
// GoVersions that features in x/tools can be gated to.
|
||||||
|
const (
|
||||||
|
Go1_18 = "go1.18"
|
||||||
|
Go1_19 = "go1.19"
|
||||||
|
Go1_20 = "go1.20"
|
||||||
|
Go1_21 = "go1.21"
|
||||||
|
Go1_22 = "go1.22"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Future is an invalid unknown Go version sometime in the future.
|
||||||
|
// Do not use directly with Compare.
|
||||||
|
const Future = ""
|
||||||
|
|
||||||
|
// AtLeast reports whether the file version v comes after a Go release.
|
||||||
|
//
|
||||||
|
// Use this predicate to enable a behavior once a certain Go release
|
||||||
|
// has happened (and stays enabled in the future).
|
||||||
|
func AtLeast(v, release string) bool {
|
||||||
|
if v == Future {
|
||||||
|
return true // an unknown future version is always after y.
|
||||||
|
}
|
||||||
|
return Compare(Lang(v), Lang(release)) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before reports whether the file version v is strictly before a Go release.
|
||||||
|
//
|
||||||
|
// Use this predicate to disable a behavior once a certain Go release
|
||||||
|
// has happened (and stays enabled in the future).
|
||||||
|
func Before(v, release string) bool {
|
||||||
|
if v == Future {
|
||||||
|
return false // an unknown future version happens after y.
|
||||||
|
}
|
||||||
|
return Compare(Lang(v), Lang(release)) < 0
|
||||||
|
}
|
172
vendor/golang.org/x/tools/internal/versions/gover.go
generated
vendored
Normal file
172
vendor/golang.org/x/tools/internal/versions/gover.go
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This is a fork of internal/gover for use by x/tools until
|
||||||
|
// go1.21 and earlier are no longer supported by x/tools.
|
||||||
|
|
||||||
|
package versions
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// A gover is a parsed Go gover: major[.Minor[.Patch]][kind[pre]]
|
||||||
|
// The numbers are the original decimal strings to avoid integer overflows
|
||||||
|
// and since there is very little actual math. (Probably overflow doesn't matter in practice,
|
||||||
|
// but at the time this code was written, there was an existing test that used
|
||||||
|
// go1.99999999999, which does not fit in an int on 32-bit platforms.
|
||||||
|
// The "big decimal" representation avoids the problem entirely.)
|
||||||
|
type gover struct {
|
||||||
|
major string // decimal
|
||||||
|
minor string // decimal or ""
|
||||||
|
patch string // decimal or ""
|
||||||
|
kind string // "", "alpha", "beta", "rc"
|
||||||
|
pre string // decimal or ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare returns -1, 0, or +1 depending on whether
|
||||||
|
// x < y, x == y, or x > y, interpreted as toolchain versions.
|
||||||
|
// The versions x and y must not begin with a "go" prefix: just "1.21" not "go1.21".
|
||||||
|
// Malformed versions compare less than well-formed versions and equal to each other.
|
||||||
|
// The language version "1.21" compares less than the release candidate and eventual releases "1.21rc1" and "1.21.0".
|
||||||
|
func compare(x, y string) int {
|
||||||
|
vx := parse(x)
|
||||||
|
vy := parse(y)
|
||||||
|
|
||||||
|
if c := cmpInt(vx.major, vy.major); c != 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
if c := cmpInt(vx.minor, vy.minor); c != 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
if c := cmpInt(vx.patch, vy.patch); c != 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
if c := strings.Compare(vx.kind, vy.kind); c != 0 { // "" < alpha < beta < rc
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
if c := cmpInt(vx.pre, vy.pre); c != 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// lang returns the Go language version. For example, lang("1.2.3") == "1.2".
|
||||||
|
func lang(x string) string {
|
||||||
|
v := parse(x)
|
||||||
|
if v.minor == "" || v.major == "1" && v.minor == "0" {
|
||||||
|
return v.major
|
||||||
|
}
|
||||||
|
return v.major + "." + v.minor
|
||||||
|
}
|
||||||
|
|
||||||
|
// isValid reports whether the version x is valid.
|
||||||
|
func isValid(x string) bool {
|
||||||
|
return parse(x) != gover{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse parses the Go version string x into a version.
|
||||||
|
// It returns the zero version if x is malformed.
|
||||||
|
func parse(x string) gover {
|
||||||
|
var v gover
|
||||||
|
|
||||||
|
// Parse major version.
|
||||||
|
var ok bool
|
||||||
|
v.major, x, ok = cutInt(x)
|
||||||
|
if !ok {
|
||||||
|
return gover{}
|
||||||
|
}
|
||||||
|
if x == "" {
|
||||||
|
// Interpret "1" as "1.0.0".
|
||||||
|
v.minor = "0"
|
||||||
|
v.patch = "0"
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse . before minor version.
|
||||||
|
if x[0] != '.' {
|
||||||
|
return gover{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse minor version.
|
||||||
|
v.minor, x, ok = cutInt(x[1:])
|
||||||
|
if !ok {
|
||||||
|
return gover{}
|
||||||
|
}
|
||||||
|
if x == "" {
|
||||||
|
// Patch missing is same as "0" for older versions.
|
||||||
|
// Starting in Go 1.21, patch missing is different from explicit .0.
|
||||||
|
if cmpInt(v.minor, "21") < 0 {
|
||||||
|
v.patch = "0"
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse patch if present.
|
||||||
|
if x[0] == '.' {
|
||||||
|
v.patch, x, ok = cutInt(x[1:])
|
||||||
|
if !ok || x != "" {
|
||||||
|
// Note that we are disallowing prereleases (alpha, beta, rc) for patch releases here (x != "").
|
||||||
|
// Allowing them would be a bit confusing because we already have:
|
||||||
|
// 1.21 < 1.21rc1
|
||||||
|
// But a prerelease of a patch would have the opposite effect:
|
||||||
|
// 1.21.3rc1 < 1.21.3
|
||||||
|
// We've never needed them before, so let's not start now.
|
||||||
|
return gover{}
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse prerelease.
|
||||||
|
i := 0
|
||||||
|
for i < len(x) && (x[i] < '0' || '9' < x[i]) {
|
||||||
|
if x[i] < 'a' || 'z' < x[i] {
|
||||||
|
return gover{}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
return gover{}
|
||||||
|
}
|
||||||
|
v.kind, x = x[:i], x[i:]
|
||||||
|
if x == "" {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
v.pre, x, ok = cutInt(x)
|
||||||
|
if !ok || x != "" {
|
||||||
|
return gover{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// cutInt scans the leading decimal number at the start of x to an integer
|
||||||
|
// and returns that value and the rest of the string.
|
||||||
|
func cutInt(x string) (n, rest string, ok bool) {
|
||||||
|
i := 0
|
||||||
|
for i < len(x) && '0' <= x[i] && x[i] <= '9' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i == 0 || x[0] == '0' && i != 1 { // no digits or unnecessary leading zero
|
||||||
|
return "", "", false
|
||||||
|
}
|
||||||
|
return x[:i], x[i:], true
|
||||||
|
}
|
||||||
|
|
||||||
|
// cmpInt returns cmp.Compare(x, y) interpreting x and y as decimal numbers.
|
||||||
|
// (Copied from golang.org/x/mod/semver's compareInt.)
|
||||||
|
func cmpInt(x, y string) int {
|
||||||
|
if x == y {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if len(x) < len(y) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if len(x) > len(y) {
|
||||||
|
return +1
|
||||||
|
}
|
||||||
|
if x < y {
|
||||||
|
return -1
|
||||||
|
} else {
|
||||||
|
return +1
|
||||||
|
}
|
||||||
|
}
|
38
vendor/golang.org/x/tools/internal/versions/types.go
generated
vendored
Normal file
38
vendor/golang.org/x/tools/internal/versions/types.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2023 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 versions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileVersion returns a file's Go version.
|
||||||
|
// The reported version is an unknown Future version if a
|
||||||
|
// version cannot be determined.
|
||||||
|
func FileVersion(info *types.Info, file *ast.File) string {
|
||||||
|
// In tools built with Go >= 1.22, the Go version of a file
|
||||||
|
// follow a cascades of sources:
|
||||||
|
// 1) types.Info.FileVersion, which follows the cascade:
|
||||||
|
// 1.a) file version (ast.File.GoVersion),
|
||||||
|
// 1.b) the package version (types.Config.GoVersion), or
|
||||||
|
// 2) is some unknown Future version.
|
||||||
|
//
|
||||||
|
// File versions require a valid package version to be provided to types
|
||||||
|
// in Config.GoVersion. Config.GoVersion is either from the package's module
|
||||||
|
// or the toolchain (go run). This value should be provided by go/packages
|
||||||
|
// or unitchecker.Config.GoVersion.
|
||||||
|
if v := info.FileVersions[file]; IsValid(v) {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
// Note: we could instead return runtime.Version() [if valid].
|
||||||
|
// This would act as a max version on what a tool can support.
|
||||||
|
return Future
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitFileVersions initializes info to record Go versions for Go files.
|
||||||
|
func InitFileVersions(info *types.Info) {
|
||||||
|
info.FileVersions = make(map[*ast.File]string)
|
||||||
|
}
|
57
vendor/golang.org/x/tools/internal/versions/versions.go
generated
vendored
Normal file
57
vendor/golang.org/x/tools/internal/versions/versions.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2023 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 versions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Note: If we use build tags to use go/versions when go >=1.22,
|
||||||
|
// we run into go.dev/issue/53737. Under some operations users would see an
|
||||||
|
// import of "go/versions" even if they would not compile the file.
|
||||||
|
// For example, during `go get -u ./...` (go.dev/issue/64490) we do not try to include
|
||||||
|
// For this reason, this library just a clone of go/versions for the moment.
|
||||||
|
|
||||||
|
// Lang returns the Go language version for version x.
|
||||||
|
// If x is not a valid version, Lang returns the empty string.
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// Lang("go1.21rc2") = "go1.21"
|
||||||
|
// Lang("go1.21.2") = "go1.21"
|
||||||
|
// Lang("go1.21") = "go1.21"
|
||||||
|
// Lang("go1") = "go1"
|
||||||
|
// Lang("bad") = ""
|
||||||
|
// Lang("1.21") = ""
|
||||||
|
func Lang(x string) string {
|
||||||
|
v := lang(stripGo(x))
|
||||||
|
if v == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return x[:2+len(v)] // "go"+v without allocation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare returns -1, 0, or +1 depending on whether
|
||||||
|
// x < y, x == y, or x > y, interpreted as Go versions.
|
||||||
|
// The versions x and y must begin with a "go" prefix: "go1.21" not "1.21".
|
||||||
|
// Invalid versions, including the empty string, compare less than
|
||||||
|
// valid versions and equal to each other.
|
||||||
|
// The language version "go1.21" compares less than the
|
||||||
|
// release candidate and eventual releases "go1.21rc1" and "go1.21.0".
|
||||||
|
// Custom toolchain suffixes are ignored during comparison:
|
||||||
|
// "go1.21.0" and "go1.21.0-bigcorp" are equal.
|
||||||
|
func Compare(x, y string) int { return compare(stripGo(x), stripGo(y)) }
|
||||||
|
|
||||||
|
// IsValid reports whether the version x is valid.
|
||||||
|
func IsValid(x string) bool { return isValid(stripGo(x)) }
|
||||||
|
|
||||||
|
// stripGo converts from a "go1.21" version to a "1.21" version.
|
||||||
|
// If v does not start with "go", stripGo returns the empty string (a known invalid version).
|
||||||
|
func stripGo(v string) string {
|
||||||
|
v, _, _ = strings.Cut(v, "-") // strip -bigcorp suffix.
|
||||||
|
if len(v) < 2 || v[:2] != "go" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return v[2:]
|
||||||
|
}
|
16
vendor/modules.txt
vendored
16
vendor/modules.txt
vendored
@ -79,15 +79,14 @@ golang.org/x/arch/x86/x86asm
|
|||||||
golang.org/x/exp/constraints
|
golang.org/x/exp/constraints
|
||||||
golang.org/x/exp/maps
|
golang.org/x/exp/maps
|
||||||
golang.org/x/exp/slices
|
golang.org/x/exp/slices
|
||||||
# golang.org/x/mod v0.20.0
|
# golang.org/x/mod v0.21.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.22.0
|
||||||
golang.org/x/mod/semver
|
golang.org/x/mod/semver
|
||||||
# golang.org/x/sync v0.8.0
|
# golang.org/x/sync v0.8.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
golang.org/x/sync/errgroup
|
golang.org/x/sync/errgroup
|
||||||
# golang.org/x/sys v0.26.0
|
# golang.org/x/sys v0.26.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
golang.org/x/sys/execabs
|
|
||||||
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-20241106142447-58a1122356f5
|
# golang.org/x/telemetry v0.0.0-20241106142447-58a1122356f5
|
||||||
@ -101,24 +100,25 @@ golang.org/x/telemetry/internal/crashmonitor
|
|||||||
golang.org/x/telemetry/internal/mmap
|
golang.org/x/telemetry/internal/mmap
|
||||||
golang.org/x/telemetry/internal/telemetry
|
golang.org/x/telemetry/internal/telemetry
|
||||||
golang.org/x/telemetry/internal/upload
|
golang.org/x/telemetry/internal/upload
|
||||||
# golang.org/x/tools v0.14.0
|
# golang.org/x/tools v0.26.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.22.0
|
||||||
golang.org/x/tools/go/gcexportdata
|
golang.org/x/tools/go/gcexportdata
|
||||||
golang.org/x/tools/go/internal/packagesdriver
|
|
||||||
golang.org/x/tools/go/packages
|
golang.org/x/tools/go/packages
|
||||||
golang.org/x/tools/go/types/objectpath
|
golang.org/x/tools/go/types/objectpath
|
||||||
|
golang.org/x/tools/go/types/typeutil
|
||||||
|
golang.org/x/tools/internal/aliases
|
||||||
golang.org/x/tools/internal/event
|
golang.org/x/tools/internal/event
|
||||||
golang.org/x/tools/internal/event/core
|
golang.org/x/tools/internal/event/core
|
||||||
golang.org/x/tools/internal/event/keys
|
golang.org/x/tools/internal/event/keys
|
||||||
golang.org/x/tools/internal/event/label
|
golang.org/x/tools/internal/event/label
|
||||||
golang.org/x/tools/internal/event/tag
|
|
||||||
golang.org/x/tools/internal/gcimporter
|
golang.org/x/tools/internal/gcimporter
|
||||||
golang.org/x/tools/internal/gocommand
|
golang.org/x/tools/internal/gocommand
|
||||||
golang.org/x/tools/internal/packagesinternal
|
golang.org/x/tools/internal/packagesinternal
|
||||||
golang.org/x/tools/internal/pkgbits
|
golang.org/x/tools/internal/pkgbits
|
||||||
golang.org/x/tools/internal/tokeninternal
|
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
|
||||||
|
golang.org/x/tools/internal/versions
|
||||||
# gopkg.in/yaml.v3 v3.0.1
|
# gopkg.in/yaml.v3 v3.0.1
|
||||||
## explicit
|
## explicit
|
||||||
gopkg.in/yaml.v3
|
gopkg.in/yaml.v3
|
||||||
|
Loading…
Reference in New Issue
Block a user