mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
Fresh dep ensure
This commit is contained in:
54
vendor/k8s.io/kubernetes/third_party/forked/etcd221/pkg/fileutil/BUILD
generated
vendored
54
vendor/k8s.io/kubernetes/third_party/forked/etcd221/pkg/fileutil/BUILD
generated
vendored
@ -23,54 +23,14 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"fileutil.go",
|
||||
"lock_plan9.go",
|
||||
"lock_solaris.go",
|
||||
"lock_unix.go",
|
||||
"lock_windows.go",
|
||||
"perallocate_unsupported.go",
|
||||
"preallocate.go",
|
||||
"purge.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"lock_unix.go",
|
||||
"preallocate.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"lock_plan9.go",
|
||||
"perallocate_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"lock_solaris.go",
|
||||
"perallocate_unsupported.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"lock_windows.go",
|
||||
"perallocate_unsupported.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/third_party/forked/etcd221/pkg/fileutil",
|
||||
deps = [
|
||||
"//vendor/github.com/coreos/pkg/capnslog:go_default_library",
|
||||
|
6
vendor/k8s.io/kubernetes/third_party/forked/etcd221/wal/walpb/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/third_party/forked/etcd221/wal/walpb/BUILD
generated
vendored
@ -29,9 +29,3 @@ filegroup(
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "go_default_library_protos",
|
||||
srcs = ["record.proto"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
67
vendor/k8s.io/kubernetes/third_party/forked/etcd237/pkg/fileutil/BUILD
generated
vendored
67
vendor/k8s.io/kubernetes/third_party/forked/etcd237/pkg/fileutil/BUILD
generated
vendored
@ -24,65 +24,16 @@ go_library(
|
||||
srcs = [
|
||||
"fileutil.go",
|
||||
"lock.go",
|
||||
"lock_plan9.go",
|
||||
"lock_solaris.go",
|
||||
"lock_unix.go",
|
||||
"lock_windows.go",
|
||||
"perallocate_unsupported.go",
|
||||
"preallocate.go",
|
||||
"purge.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
"sync.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
"sync.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
"sync.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
"sync.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"lock_unix.go",
|
||||
"preallocate.go",
|
||||
"sync_linux.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
"sync.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
"sync.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"lock_unix.go",
|
||||
"perallocate_unsupported.go",
|
||||
"sync.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"lock_plan9.go",
|
||||
"perallocate_unsupported.go",
|
||||
"sync.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"lock_solaris.go",
|
||||
"perallocate_unsupported.go",
|
||||
"sync.go",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"lock_windows.go",
|
||||
"perallocate_unsupported.go",
|
||||
"sync.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
"sync.go",
|
||||
"sync_linux.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/third_party/forked/etcd237/pkg/fileutil",
|
||||
deps = [
|
||||
"//vendor/github.com/coreos/pkg/capnslog:go_default_library",
|
||||
|
6
vendor/k8s.io/kubernetes/third_party/forked/etcd237/wal/walpb/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/third_party/forked/etcd237/wal/walpb/BUILD
generated
vendored
@ -29,9 +29,3 @@ filegroup(
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "go_default_library_protos",
|
||||
srcs = ["record.proto"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
1
vendor/k8s.io/kubernetes/third_party/forked/godep/.gitignore
generated
vendored
Normal file
1
vendor/k8s.io/kubernetes/third_party/forked/godep/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
/godep
|
34
vendor/k8s.io/kubernetes/third_party/forked/godep/.travis.yml
generated
vendored
Normal file
34
vendor/k8s.io/kubernetes/third_party/forked/godep/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
language: go
|
||||
sudo: false
|
||||
go: 1.6
|
||||
script:
|
||||
# Godep's unit tests run git, and git complains
|
||||
# if we don't set these config parameters.
|
||||
# We put dummy values here because they don't matter.
|
||||
- git config --global user.email "you@example.com"
|
||||
- git config --global user.name "Your Name"
|
||||
- test -z "$(go fmt)"
|
||||
- go vet
|
||||
- go test -v
|
||||
- go test -v -race
|
||||
- test -z "$(goimports -l .)"
|
||||
before_install:
|
||||
- go get golang.org/x/tools/cmd/goimports
|
||||
before_deploy:
|
||||
- export OS_TARGETS="linux darwin windows"
|
||||
- export ARCH_TARGETS="386 amd64"
|
||||
- go get github.com/mitchellh/gox
|
||||
- gox -os "$OS_TARGETS" -arch="$ARCH_TARGETS"
|
||||
deploy:
|
||||
skip_cleanup: true
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: Q1JP8LziaXMTxFmNXiyC1YhS9e4M4WnI6UDjRTMf6mm1LZeJyUFOCCtXnifL7RyCIR1hpjp6s8M1aWE+NpuweF96IZI3Uk4ASx5C8FePC4qvhsCdtJ2sLD2GTIrp9b0MS9/+ao20AIbpVDSaLaF9IjqXpMxMyM0P8P5coRTkwItlGxmQbVJW3YuiYcPa8UojwM4EyafO2CIoUKapW8lwb9KcimBJV8PfF/XZjPVhMkn2ABhh5Hqbn2zBJtvPYMMzi0CnY50JQF5LwN3vGTMpTsRP+lOLCNbOWfkl+2hgG7VpKrtx+cX62knOodpF457sIJ31KUzmeLUVBejTGb1zuVeTojuyi8Huo8YBIBCcN+p3Dqd+n2ZK45mIrheGiEJIkf/vI4MI6A01Nu/o+xU0IPsVfAL/xU5j5nntEGfFWVoclPrl9qcfqf74xdRcARzcCJVmdc8iw49DBDHJfnPa3zxzVz//00+Rz6mZXmhk+Npk/HLLNW59vmJIjP+8XOtPor7dST9HrS1a9AcnmIjNuw9yfbwK5769SDVxCKgqNwXW/Dy5F39aIH5AL4I4y9hCEeeT8ctvSJHGOyiB9MWU5jnt5tluPtz5opG51tFXnIYP/XaWpTfO+eJ6x55pbwT+n3LfRS5l1POM+jGAFF1MFWwc14RY7qynEIEzm4Wb/UE=
|
||||
file:
|
||||
- godep_darwin_amd64
|
||||
- godep_linux_amd64
|
||||
- godep_windows_386.exe
|
||||
- godep_windows_amd64.exe
|
||||
on:
|
||||
tags: true
|
||||
repo: tools/godep
|
57
vendor/k8s.io/kubernetes/third_party/forked/godep/BUILD
generated
vendored
Normal file
57
vendor/k8s.io/kubernetes/third_party/forked/godep/BUILD
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"dep.go",
|
||||
"diff.go",
|
||||
"doc.go",
|
||||
"errors.go",
|
||||
"get.go",
|
||||
"go.go",
|
||||
"godepfile.go",
|
||||
"license.go",
|
||||
"list.go",
|
||||
"main.go",
|
||||
"msg.go",
|
||||
"path.go",
|
||||
"pkg.go",
|
||||
"restore.go",
|
||||
"rewrite.go",
|
||||
"save.go",
|
||||
"update.go",
|
||||
"util.go",
|
||||
"vcs.go",
|
||||
"version.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/third_party/forked/godep",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//vendor/github.com/kr/fs:go_default_library",
|
||||
"//vendor/github.com/kr/pretty:go_default_library",
|
||||
"//vendor/github.com/pmezard/go-difflib/difflib:go_default_library",
|
||||
"//vendor/golang.org/x/tools/go/vcs:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "godep",
|
||||
embed = [":go_default_library"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
412
vendor/k8s.io/kubernetes/third_party/forked/godep/Changelog.md
generated
vendored
Normal file
412
vendor/k8s.io/kubernetes/third_party/forked/godep/Changelog.md
generated
vendored
Normal file
@ -0,0 +1,412 @@
|
||||
#v80 (2018/01/26)
|
||||
|
||||
* Address lin/vet feedback.
|
||||
|
||||
#v79 (2017/02/01)
|
||||
|
||||
* Fixes #531: fullPackageInDir didn't capture the error from fillPackage()
|
||||
|
||||
#v78 (2017/01/19)
|
||||
|
||||
* Don't use build.ImportDir when discovering packages for the package spec. Fixes #529
|
||||
|
||||
#v77 (2017/01/13)
|
||||
|
||||
* Don't include quotes around hg revisions
|
||||
|
||||
#v76 (2017/01/10)
|
||||
|
||||
* Default to vendor being on unless older go versions.
|
||||
|
||||
#v75 (2016/11/02)
|
||||
|
||||
* Add "AUTHORS" and "CONTRIBUTORS" to legal files list: https://github.com/tools/godep/pull/522
|
||||
|
||||
#v74 (2016/06/01)
|
||||
|
||||
* Enable vendor/ on go1.7
|
||||
* No longer use a godep workspace, use vendor/ (yay!)
|
||||
* Notify that support for Godep workspaces will be removed once go1.8 ships
|
||||
|
||||
#v73 (2016/05/31)
|
||||
|
||||
* Fix permission changes on Windows via @alexbrand. Closes #481.
|
||||
|
||||
#v72 (2016/05/27)
|
||||
|
||||
* Improve handling of git remote show origin. Should help in cases where remote HEAD is ambiguous.
|
||||
* Add ISSUE_TEMPLATE
|
||||
|
||||
#v71 (2016/05/24)
|
||||
|
||||
* Preserve permissions on copied files.
|
||||
|
||||
#v70 (2016/05/20)
|
||||
|
||||
* Fix the May changelog dates
|
||||
* No need to call build.Import, we already have the root of the dependency. Fixes an additional comment on #365
|
||||
|
||||
#v69 (2016/05/16)
|
||||
|
||||
* Make sure `devel-<short sha>` enabled `vendor/` unless there is a classic Godep _workspace already.
|
||||
|
||||
#v68 (2016/05/16)
|
||||
|
||||
* `devel-<short sha>` is always considered newer than any released go version
|
||||
|
||||
#v67 (2016/05/13)
|
||||
|
||||
* Attempt to handle missing deps a little better.
|
||||
|
||||
#v66 (2016/05/10)
|
||||
|
||||
* Use `git remote show origin` to find the default branch when restoring a git based package repository that is in detached head state
|
||||
|
||||
#v65 (2016/05/09)
|
||||
|
||||
* Rewrite update so that it considers new transitive dependencies, both in the same repo and outside of it.
|
||||
|
||||
#v64 (2016/05/09)
|
||||
|
||||
* godep update golang.org/x/tools/go/vcs
|
||||
|
||||
#v63 (2016/05/03)
|
||||
|
||||
* Support recording devel-<short sha> so development versions of Go can be matched
|
||||
|
||||
#v62 (2016/04/07)
|
||||
|
||||
* Note new go1.6+ behavior of not checking out master in README / restore help text.
|
||||
|
||||
#v61 (2016/04/06)
|
||||
|
||||
* Obey go version build tags based on recorded major go version. Fixes #448.
|
||||
|
||||
#v60 (2016/03/18)
|
||||
|
||||
* Make the $GOPATH check a warning.
|
||||
|
||||
#v59 (2016/03/18)
|
||||
|
||||
* Enforce requirement to be inside of a go src directory. A lot of time is usually spent
|
||||
tracking down bug reports where people are doign stuff from outside of their $GOPATH. This
|
||||
should help with that, at least until there it time to properly test godep use outside of a
|
||||
$GOPATH and fix the issues.
|
||||
|
||||
#v58 (2016/03/15)
|
||||
|
||||
* Add GodepVersion to Godeps.json file so that as godep changes / adds features / fixes bugs we can know which version of godep most recently wrote out the file.
|
||||
|
||||
#v57 (2016/03/07)
|
||||
|
||||
* Don't use `git rev-parse --show-toplevel` to determine git repo roots as it resolves symlinks: https://github.com/tools/godep/pull/418
|
||||
|
||||
# v56 (2016/02/26)
|
||||
|
||||
* replace path comparisons with case insensitive pathEqual()
|
||||
* add versionString() to debug output
|
||||
* Send log output to Stderr
|
||||
|
||||
# v55 2016/02/22
|
||||
|
||||
* re-saved deps to clean out extra stuff (see v54; godep restore; godep save -r=false; rm -rf Godeps; godep save -r). We're still using a workspace with rewrites so users of older go version can still go get this tool.
|
||||
* Replace simple == with strings.EqualFold in listFiles to avoid problems with case insensitive filesystems ("Code" != "code" when doing a byte by byte comparison)
|
||||
|
||||
# v54 2016/02/22
|
||||
|
||||
* Update some docs around vendor/
|
||||
* More precise recording of dependencies. Removed recursive copying of sub directories of a package (precise vendoring). This should allow using `./...` with the go tool for compilation of project using `vendor/`. See https://github.com/tools/godep/pull/415
|
||||
|
||||
# v53 2016/02/11
|
||||
|
||||
* Disable VendorExperiment if a godep workspace already exists.
|
||||
|
||||
# v52 2016/01/27
|
||||
|
||||
* Trim 'rc' out of go version strings when determining major version.
|
||||
|
||||
# v51 2016/01/21
|
||||
|
||||
* Trim 'beta' out of go version strings when determining major version.
|
||||
|
||||
# v50 2016/01/19
|
||||
|
||||
* More verbose output on save -v.
|
||||
|
||||
# v49 2016/01/13
|
||||
|
||||
* Add UK spelling license/licence to the pile + fix up a bunch of typos
|
||||
* Clarify tag handling in docs
|
||||
|
||||
# v48 2016/01/13
|
||||
|
||||
* Abort restore if there is no $GOPATH set.
|
||||
|
||||
# v47 2016/01/12
|
||||
|
||||
* Dev versions of go should honor the current meaning of GO15VENDOREXPERIMENT
|
||||
|
||||
# v46 2016/01/03
|
||||
|
||||
* Record "devel" when the release is a devel release of go (compiled from git).
|
||||
|
||||
# v45 2015/12/28
|
||||
|
||||
* Upcase windows drive letters before comparing. Fixes #383.
|
||||
|
||||
# v44 2015/12/23
|
||||
|
||||
* Clean package roots when attempting to find a vendor directory so we don't loop forever.
|
||||
* Fixes 382
|
||||
|
||||
# v43 2015/12/22
|
||||
|
||||
* Better error messages when parsing Godeps.json: Fixes #372
|
||||
|
||||
# v42 2015/12/22
|
||||
|
||||
* Fix a bunch of GO15VENDOREXPERIMENT issues
|
||||
* Find package directories better. Previously we used build.FindOnly which didn't work the way I expected it to (any dir would work w/o error).
|
||||
* Set the VendorExperiment bool based on go version as 1.6 defaults to on.
|
||||
* A bunch of extra debugging for use while sanity checking myself.
|
||||
* vendor flag for test structs.
|
||||
* Some tests for vendor/ stuff:
|
||||
* Basic Test
|
||||
* Transitive
|
||||
* Transitive, across GOPATHs + collapse vendor/ directories.
|
||||
* Should Fix #358
|
||||
|
||||
# v41 2015/12/17
|
||||
|
||||
* Don't rewrite packages outside of the project. This would happen if you specified
|
||||
an external package for vendoring when you ran `goodep save -r ./... github.com/some/other/package`
|
||||
|
||||
# v40 2015/12/17
|
||||
|
||||
* When downloading a dependency, create the base directory if needed.
|
||||
|
||||
# v39 2015/12/16
|
||||
|
||||
* Record only the major go version (ex. go1.5) instead of the complete string.
|
||||
|
||||
# v38 2015/12/16
|
||||
|
||||
* Replace `go get`, further fix up restore error handling/reporting.
|
||||
* Fixes #186
|
||||
* Don't bother restoring/downloading if already done.
|
||||
|
||||
# v37 2015/12/15
|
||||
|
||||
* Change up how download/restore works a little
|
||||
* Try to load the package after downloading/restoring. Previously
|
||||
that was done too early in the process.
|
||||
* make previous verbose output debug output
|
||||
* report a typed error instead of a string from listPackage so it can
|
||||
be asserted to provide a nicer error.
|
||||
* Catch go get errors that say there are no go files found. See code
|
||||
comment as to why.
|
||||
* do *all* downloading during download phase.
|
||||
|
||||
# v36 2015/12/14
|
||||
|
||||
* Fixes #358: Using wrong variable. Will add test after release.
|
||||
|
||||
# v35 2015/12/11
|
||||
|
||||
* Fixes #356: Major performance regressions in v34
|
||||
* Enable cpu profiling via flag on save.
|
||||
* Cache packages by dir
|
||||
* Don't do a full import pass on deps for packages in the GOROOT
|
||||
* create a bit less garbage at times
|
||||
* Generalize -v & -d flags
|
||||
|
||||
# v34 2015/12/08
|
||||
|
||||
* We now use build.Context to help locate packages only and do our own parsing (via go/ast).
|
||||
* Fixes reported issues caused by v33 (Removal of `go list`):
|
||||
* #345: Bug in godep restore
|
||||
* #346: Fix loading a dot package
|
||||
* #348: Godep save issue when importing lib/pq
|
||||
* #350: undefined: build.MultiplePackageError
|
||||
* #351: stow away helper files
|
||||
* #353: cannot find package "appengine"
|
||||
* Don't process imports of `.go` files tagged with the `appengine` build tag.
|
||||
|
||||
# v33 2015/12/07
|
||||
|
||||
* Replace the use of `go list`. This is a large change although all existing tests pass.
|
||||
* Don't process the imports of `.go` files with the `ignore` build tag.
|
||||
|
||||
# v32 2015/12/02
|
||||
|
||||
* Eval Symlinks in Contains() check.
|
||||
|
||||
# v31 2015/12/02
|
||||
|
||||
* In restore, mention which package had the problem -- @shurcool
|
||||
|
||||
# v30 2015/11/25
|
||||
|
||||
* Add `-t` flag to the `godep get` command.
|
||||
|
||||
# v29 2015/11/17
|
||||
|
||||
* Temp work around to fix issue with LICENSE files.
|
||||
|
||||
# v28 2015/11/09
|
||||
|
||||
* Make `version` an actual command.
|
||||
|
||||
# v27 2015/11/06
|
||||
|
||||
* run command once during restore -v
|
||||
|
||||
# v26 2015/11/05
|
||||
|
||||
* Better fix for the issue fixed in v25: All update paths are now path.Clean()'d
|
||||
|
||||
# v25 2015/11/05
|
||||
|
||||
* `godep update package/` == `godep update package`. Fixes #313
|
||||
|
||||
# v24 2015/11/05
|
||||
|
||||
* Honor -t during update. Fixes #312
|
||||
|
||||
# v23 2015/11/05
|
||||
|
||||
* Do not use --debug to find full revision name for mercurial repositories
|
||||
|
||||
# v22 2015/11/14
|
||||
|
||||
* s/GOVENDOREXPERIMENT/GO15VENDOREXPERIMENT :-(
|
||||
|
||||
# v21 2015/11/13
|
||||
|
||||
* Fix #310: Case insensitive fs issue
|
||||
|
||||
# v20 2015/11/13
|
||||
|
||||
* Attempt to include license files when vendoring. (@client9)
|
||||
|
||||
# v19 2015/11/3
|
||||
|
||||
* Fix conflict error message. Revisions were swapped. Also better selection of package that needs update.
|
||||
|
||||
# v18 2015/10/16
|
||||
|
||||
* Improve error message when trying to save a conflicting revision.
|
||||
|
||||
# v17 2015/10/15
|
||||
|
||||
* Fix for v16 bug. All vcs list commands now produce paths relative to the root of the vcs.
|
||||
|
||||
# v16 2015/10/15
|
||||
|
||||
* Determine repo root using vcs commands and use that instead of dep.dir
|
||||
|
||||
# v15 2015/10/14
|
||||
|
||||
* Update .travis.yml file to do releases to github
|
||||
|
||||
# v14 2015/10/08
|
||||
|
||||
* Don't print out a workspace path when GO15VENDOREXPERIMENT is active. The vendor/ directory is not a valid workspace, so can't be added to your $GOPATH.
|
||||
|
||||
# v13 2015/10/07
|
||||
|
||||
* Do restores in 2 separate steps, first download all deps and then check out the recorded revisions.
|
||||
* Update Changelog date format
|
||||
|
||||
# v12 2015/09/22
|
||||
|
||||
* Extract errors into separate file.
|
||||
|
||||
# v11 2015/08/22
|
||||
|
||||
* Amend code to pass golint.
|
||||
|
||||
# v10 2015/09/21
|
||||
|
||||
* Analyse vendored package test dependencies.
|
||||
* Update documentation.
|
||||
|
||||
# v9 2015/09/17
|
||||
|
||||
* Don't save test dependencies by default.
|
||||
|
||||
# v8 2015/09/17
|
||||
|
||||
* Reorganize code.
|
||||
|
||||
# v7 2015/09/09
|
||||
|
||||
* Add verbose flag.
|
||||
* Skip untracked files.
|
||||
* Add VCS list command.
|
||||
|
||||
# v6 2015/09/04
|
||||
|
||||
* Revert ignoring testdata directories and instead ignore it while
|
||||
processing Go files and copy the whole directory unmodified.
|
||||
|
||||
# v5 2015/09/04
|
||||
|
||||
* Fix vcs selection in restore command to work as go get does
|
||||
|
||||
# v4 2015/09/03
|
||||
|
||||
* Remove the deprecated copy option.
|
||||
|
||||
# v3 2015/08/26
|
||||
|
||||
* Ignore testdata directories
|
||||
|
||||
# v2 2015/08/11
|
||||
|
||||
* Include command line packages in the set to copy
|
||||
|
||||
This is a simplification to how we define the behavior
|
||||
of the save command. Now it has two distinct package
|
||||
parameters, the "root set" and the "destination", and
|
||||
they have clearer roles. The packages listed on the
|
||||
command line form the root set; they and all their
|
||||
dependencies will be copied into the Godeps directory.
|
||||
Additionally, the destination (always ".") will form the
|
||||
initial list of "seen" import paths to exclude from
|
||||
copying.
|
||||
|
||||
In the common case, the root set is equal to the
|
||||
destination, so the effective behavior doesn't change.
|
||||
This is primarily just a simpler definition. However, if
|
||||
the user specifies a package on the command line that
|
||||
lives outside of . then that package will be copied.
|
||||
|
||||
As a side effect, there's a simplification to the way we
|
||||
add packages to the initial "seen" set. Formerly, to
|
||||
avoid copying dependencies unnecessarily, we would try
|
||||
to find the root of the VCS repo for each package in the
|
||||
root set, and mark the import path of the entire repo as
|
||||
seen. This meant for a repo at path C, if destination
|
||||
C/S imports C/T, we would not copy C/T into C/S/Godeps.
|
||||
Now we don't treat the repo root specially, and as
|
||||
mentioned above, the destination alone is considered
|
||||
seen.
|
||||
|
||||
This also means we don't require listed packages to be
|
||||
in VCS unless they're outside of the destination.
|
||||
|
||||
# v1 2015/07/20
|
||||
|
||||
* godep version command
|
||||
|
||||
Output the version as well as some godep runtime information that is
|
||||
useful for debugging user's issues.
|
||||
|
||||
The version const would be bumped each time a PR is merged into master
|
||||
to ensure that we'll be able to tell which version someone got when they
|
||||
did a `go get github.com/tools/godep`.
|
||||
|
||||
# Older changes
|
||||
|
||||
Many and more, see `git log -p`
|
22
vendor/k8s.io/kubernetes/third_party/forked/godep/FAQ.md
generated
vendored
Normal file
22
vendor/k8s.io/kubernetes/third_party/forked/godep/FAQ.md
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
## Why do I need to check in `vendor/`?
|
||||
|
||||
godep's primary concern is to allow you to repeatably build your project. Your
|
||||
dependencies are part of that project. Without them it won't build. Not
|
||||
committing `vendor/` adds additional external dependencies that are outside of
|
||||
your control. In Go, fetching packages is tied to multiple external systems
|
||||
(DNS, web servers, etc). Over time other developers or code hosting sites may
|
||||
discontinue service, delete code, force push, or take any number of other
|
||||
actions that may make a package unreachable. Therefore it's the opinion of the
|
||||
godep authors that `vendor/` should always be checked in.
|
||||
|
||||
## Should I use `godep restore`?
|
||||
|
||||
Probably not, unless you **need** to. Situations where you would **need** to are:
|
||||
|
||||
1. Using older Godep Workspaces (`Godeps/_workspace`) and not using `godep go
|
||||
<cmd>`.
|
||||
1. Resetting the state of $GOPATH to what is in your `Godeps.json` file in order
|
||||
to cleanly re-vendor everything w/o upgrading/changing any deps. This is
|
||||
useful when [migrating](https://github.com/tools/godep#migrating-to-vendor)
|
||||
from workspaces to `vendor` or when a bug is fixed in `godep` that cleans up
|
||||
a previous vendoring error.
|
28
vendor/k8s.io/kubernetes/third_party/forked/godep/License
generated
vendored
Normal file
28
vendor/k8s.io/kubernetes/third_party/forked/godep/License
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
Copyright © 2013 Keith Rarick.
|
||||
Portions Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
209
vendor/k8s.io/kubernetes/third_party/forked/godep/Readme.md
generated
vendored
Normal file
209
vendor/k8s.io/kubernetes/third_party/forked/godep/Readme.md
generated
vendored
Normal file
@ -0,0 +1,209 @@
|
||||
# Godep - Archived
|
||||
|
||||
Please use [dep](https://github.com/golang/dep) or another tool instead.
|
||||
|
||||
The rest of this readme is preserved for those that may still need its contents.
|
||||
|
||||
[](https://travis-ci.org/tools/godep)
|
||||
|
||||
[](https://godoc.org/github.com/tools/godep)
|
||||
|
||||
godep helps build packages reproducibly by fixing their dependencies.
|
||||
|
||||
This tool assumes you are working in a standard Go workspace, as described [here](http://golang.org/doc/code.html). We
|
||||
expect godep to build on Go 1.4* or newer, but you can use it on any project that works with Go 1 or newer.
|
||||
|
||||
Please check the [FAQ](FAQ.md) if you have a question.
|
||||
|
||||
## Golang Dep
|
||||
|
||||
The Go community now has the [dep](https://github.com/golang/dep) project to
|
||||
manage dependencies. Please consider trying to migrate from Godep to dep. If there
|
||||
is an issue preventing you from migrating please file an issue with dep so the
|
||||
problem can be corrected. Godep will continue to be supported for some time but
|
||||
is considered to be in a state of support rather than active feature development.
|
||||
|
||||
## Install
|
||||
|
||||
```console
|
||||
go get github.com/tools/godep
|
||||
```
|
||||
|
||||
## How to use godep with a new project
|
||||
|
||||
Assuming you've got everything working already, so you can build your project
|
||||
with `go install` and test it with `go test`, it's one command to start using:
|
||||
|
||||
```console
|
||||
godep save
|
||||
```
|
||||
|
||||
This will save a list of dependencies to the file `Godeps/Godeps.json` and copy
|
||||
their source code into `vendor/` (or `Godeps/_workspace/` when using older
|
||||
versions of Go). Godep does **not copy**:
|
||||
|
||||
- files from source repositories that are not tracked in version control.
|
||||
- `*_test.go` files.
|
||||
- `testdata` directories.
|
||||
- files outside of the go packages.
|
||||
|
||||
Godep does not process the imports of `.go` files with either the `ignore`
|
||||
or `appengine` build tags.
|
||||
|
||||
Test files and testdata directories can be saved by adding `-t`.
|
||||
|
||||
Read over the contents of `vendor/` and make sure it looks reasonable. Then
|
||||
commit the `Godeps/` and `vendor/` directories to version control.
|
||||
|
||||
## The deprecated `-r` flag
|
||||
|
||||
For older versions of Go, the `-r` flag tells save to automatically rewrite
|
||||
package import paths. This allows your code to refer directly to the copied
|
||||
dependencies in `Godeps/_workspace`. So, a package C that depends on package
|
||||
D will actually import `C/Godeps/_workspace/src/D`. This makes C's repo
|
||||
self-contained and causes `go get` to build C with the right version of all
|
||||
dependencies.
|
||||
|
||||
If you don't use `-r`, when using older version of Go, then in order to use the
|
||||
fixed dependencies and get reproducible builds, you must make sure that **every
|
||||
time** you run a Go-related command, you wrap it in one of these two ways:
|
||||
|
||||
- If the command you are running is just `go`, run it as `godep go ...`, e.g.
|
||||
`godep go install -v ./...`
|
||||
- When using a different command, set your `$GOPATH` using `godep path` as
|
||||
described below.
|
||||
|
||||
`-r` isn't necessary with go1.6+ and isn't allowed.
|
||||
|
||||
## Additional Operations
|
||||
|
||||
### Restore
|
||||
|
||||
The `godep restore` installs the
|
||||
package versions specified in `Godeps/Godeps.json` to your `$GOPATH`. This
|
||||
modifies the state of packages in your `$GOPATH`. NOTE: `godep restore` leaves
|
||||
git repositories in a detached state. `go1.6`+ no longer checks out the master
|
||||
branch when doing a `go get`, see [here](https://github.com/golang/go/commit/42206598671a44111c8f726ad33dc7b265bdf669).
|
||||
|
||||
> If you run `godep restore` in your main `$GOPATH` `go get -u` will fail on packages that are behind master.
|
||||
|
||||
Please see the [FAQ](https://github.com/tools/godep/blob/master/FAQ.md#should-i-use-godep-restore) section about restore.
|
||||
|
||||
### Edit-test Cycle
|
||||
|
||||
1. Edit code
|
||||
1. Run `godep go test`
|
||||
1. (repeat)
|
||||
|
||||
### Add a Dependency
|
||||
|
||||
To add a new package foo/bar, do this:
|
||||
|
||||
1. Run `go get foo/bar`
|
||||
1. Edit your code to import foo/bar.
|
||||
1. Run `godep save` (or `godep save ./...`).
|
||||
|
||||
### Update a Dependency
|
||||
|
||||
To update a package from your `$GOPATH`, do this:
|
||||
|
||||
1. Run `go get -u foo/bar`
|
||||
1. Run `godep update foo/bar`.
|
||||
|
||||
You can use the `...` wildcard, for example `godep update foo/...`. Before comitting the change, you'll probably want to
|
||||
inspect the changes to Godeps, for example with `git diff`, and make sure it looks reasonable.
|
||||
|
||||
## Multiple Packages
|
||||
|
||||
If your repository has more than one package, you're probably accustomed to
|
||||
running commands like `go test ./...`, `go install ./...`, and `go fmt ./...`.
|
||||
Similarly, you should run `godep save ./...` to capture the dependencies of all
|
||||
packages in your application.
|
||||
|
||||
## File Format
|
||||
|
||||
Godeps is a json file with the following structure:
|
||||
|
||||
```go
|
||||
type Godeps struct {
|
||||
ImportPath string
|
||||
GoVersion string // Abridged output of 'go version'.
|
||||
GodepVersion string // Abridged output of 'godep version'
|
||||
Packages []string // Arguments to godep save, if any.
|
||||
Deps []struct {
|
||||
ImportPath string
|
||||
Comment string // Description of commit, if present.
|
||||
Rev string // VCS-specific commit ID.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Example Godeps:
|
||||
|
||||
```json
|
||||
{
|
||||
"ImportPath": "github.com/kr/hk",
|
||||
"GoVersion": "go1.6",
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "code.google.com/p/go-netrc/netrc",
|
||||
"Rev": "28676070ab99"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kr/binarydist",
|
||||
"Rev": "3380ade90f8b0dfa3e363fd7d7e941fa857d0d13"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Migrating to vendor/
|
||||
|
||||
Godep supports the Go 1.5+ vendor/
|
||||
[experiment](https://github.com/golang/go/commit/183cc0cd41f06f83cb7a2490a499e3f9101befff)
|
||||
utilizing the same environment variable that the go tooling itself supports
|
||||
(`GO15VENDOREXPERIMENT`).
|
||||
|
||||
godep mostly works the same way as the `go` command line tool. If you have go
|
||||
1.5.X and set `GO15VENDOREXPERIMENT=1` or have go1.6.X (or devel) `vendor/`
|
||||
is enabled. **Unless** you already have a `Godeps/_workspace`. This is a safety
|
||||
feature and godep warns you about this.
|
||||
|
||||
When `vendor/` is enabled godep will write the vendored code into the top level
|
||||
`./vendor/` directory. A `./Godeps/Godeps.json` file is created to track
|
||||
the dependencies and revisions. `vendor/` is not compatible with rewrites.
|
||||
|
||||
There is currently no automated migration between the old Godeps workspace and
|
||||
the vendor directory, but the following steps should work:
|
||||
|
||||
```term
|
||||
# just to be safe
|
||||
$ unset GO15VENDOREXPERIMENT
|
||||
|
||||
# restore currently vendored deps to the $GOPATH
|
||||
$ godep restore
|
||||
|
||||
# The next line is only needed to automatically undo rewritten imports that were
|
||||
# created with godep save -r.
|
||||
$ godep save -r=false <pkg spec>
|
||||
|
||||
# Remove the old Godeps folder
|
||||
$ rm -rf Godeps
|
||||
|
||||
# If on go1.5.X to enable `vendor/`
|
||||
$ export GO15VENDOREXPERIMENT=1
|
||||
|
||||
# re-analyze deps and save to `vendor/`.
|
||||
$ godep save <pkg spec>
|
||||
|
||||
# Add the changes to your VCS
|
||||
$ git add -A . ; git commit -am "Godep workspace -> vendor/"
|
||||
|
||||
# You should see your Godeps/_workspace/src files "moved" to vendor/.
|
||||
```
|
||||
|
||||
## Releasing
|
||||
|
||||
1. Increment the version in `version.go`.
|
||||
1. Tag the commit with the same version number.
|
||||
1. Update `Changelog.md`.
|
128
vendor/k8s.io/kubernetes/third_party/forked/godep/dep.go
generated
vendored
Normal file
128
vendor/k8s.io/kubernetes/third_party/forked/godep/dep.go
generated
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A Dependency is a specific revision of a package.
|
||||
type Dependency struct {
|
||||
ImportPath string
|
||||
Comment string `json:",omitempty"` // Description of commit, if present.
|
||||
Rev string // VCS-specific commit ID.
|
||||
|
||||
// used by command save & update
|
||||
ws string // workspace
|
||||
root string // import path to repo root
|
||||
dir string // full path to package
|
||||
|
||||
// used by command update
|
||||
matched bool // selected for update by command line
|
||||
pkg *Package
|
||||
missing bool // packages is missing
|
||||
|
||||
// used by command go
|
||||
vcs *VCS
|
||||
}
|
||||
|
||||
func eqDeps(a, b []Dependency) bool {
|
||||
ok := true
|
||||
for _, da := range a {
|
||||
for _, db := range b {
|
||||
if da.ImportPath == db.ImportPath && da.Rev != db.Rev {
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
// containsPathPrefix returns whether any string in a
|
||||
// is s or a directory containing s.
|
||||
// For example, pattern ["a"] matches "a" and "a/b"
|
||||
// (but not "ab").
|
||||
func containsPathPrefix(pats []string, s string) bool {
|
||||
for _, pat := range pats {
|
||||
if pat == s || strings.HasPrefix(s, pat+"/") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func uniq(a []string) []string {
|
||||
var s string
|
||||
var i int
|
||||
if !sort.StringsAreSorted(a) {
|
||||
sort.Strings(a)
|
||||
}
|
||||
for _, t := range a {
|
||||
if t != s {
|
||||
a[i] = t
|
||||
i++
|
||||
s = t
|
||||
}
|
||||
}
|
||||
return a[:i]
|
||||
}
|
||||
|
||||
// trimGoVersion and return the major version
|
||||
func trimGoVersion(version string) (string, error) {
|
||||
if version == "devel" {
|
||||
return "devel", nil
|
||||
}
|
||||
if strings.HasPrefix(version, "devel+") || strings.HasPrefix(version, "devel-") {
|
||||
return strings.Replace(version, "devel+", "devel-", 1), nil
|
||||
}
|
||||
p := strings.Split(version, ".")
|
||||
if len(p) < 2 {
|
||||
return "", fmt.Errorf("Error determining major go version from: %q", version)
|
||||
}
|
||||
var split string
|
||||
switch {
|
||||
case strings.Contains(p[1], "beta"):
|
||||
split = "beta"
|
||||
case strings.Contains(p[1], "rc"):
|
||||
split = "rc"
|
||||
}
|
||||
if split != "" {
|
||||
p[1] = strings.Split(p[1], split)[0]
|
||||
}
|
||||
return p[0] + "." + p[1], nil
|
||||
}
|
||||
|
||||
var goVersionTestOutput = ""
|
||||
|
||||
func getGoVersion() (string, error) {
|
||||
// For testing purposes only
|
||||
if goVersionTestOutput != "" {
|
||||
return goVersionTestOutput, nil
|
||||
}
|
||||
|
||||
// Godep might have been compiled with a different
|
||||
// version, so we can't just use runtime.Version here.
|
||||
cmd := exec.Command("go", "version")
|
||||
cmd.Stderr = os.Stderr
|
||||
out, err := cmd.Output()
|
||||
return string(out), err
|
||||
}
|
||||
|
||||
// goVersion returns the major version string of the Go compiler
|
||||
// currently installed, e.g. "go1.5".
|
||||
func goVersion() (string, error) {
|
||||
out, err := getGoVersion()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
gv := strings.Split(out, " ")
|
||||
if len(gv) < 4 {
|
||||
return "", fmt.Errorf("Error splitting output of `go version`: Expected 4 or more elements, but there are < 4: %q", out)
|
||||
}
|
||||
if gv[2] == "devel" {
|
||||
return trimGoVersion(gv[2] + gv[3])
|
||||
}
|
||||
return trimGoVersion(gv[2])
|
||||
}
|
74
vendor/k8s.io/kubernetes/third_party/forked/godep/diff.go
generated
vendored
Normal file
74
vendor/k8s.io/kubernetes/third_party/forked/godep/diff.go
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/pmezard/go-difflib/difflib"
|
||||
)
|
||||
|
||||
var cmdDiff = &Command{
|
||||
Name: "diff",
|
||||
Short: "shows the diff between current and previously saved set of dependencies",
|
||||
Long: `
|
||||
Shows the difference, in a unified diff format, between the
|
||||
current set of dependencies and those generated on a
|
||||
previous 'go save' execution.
|
||||
`,
|
||||
Run: runDiff,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
func runDiff(cmd *Command, args []string) {
|
||||
gold, err := loadDefaultGodepsFile()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
pkgs := []string{"."}
|
||||
dot, err := LoadPackages(pkgs...)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
gnew := &Godeps{
|
||||
ImportPath: dot[0].ImportPath,
|
||||
GoVersion: gold.GoVersion,
|
||||
}
|
||||
|
||||
err = gnew.fill(dot, dot[0].ImportPath)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
diff, err := diffStr(&gold, gnew)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
fmt.Println(diff)
|
||||
}
|
||||
|
||||
// diffStr returns a unified diff string of two Godeps.
|
||||
func diffStr(a, b *Godeps) (string, error) {
|
||||
var ab, bb bytes.Buffer
|
||||
|
||||
_, err := a.writeTo(&ab)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
_, err = b.writeTo(&bb)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
diff := difflib.UnifiedDiff{
|
||||
A: difflib.SplitLines(ab.String()),
|
||||
B: difflib.SplitLines(bb.String()),
|
||||
FromFile: b.file(),
|
||||
ToFile: "$GOPATH",
|
||||
Context: 10,
|
||||
}
|
||||
return difflib.GetUnifiedDiffString(diff)
|
||||
}
|
22
vendor/k8s.io/kubernetes/third_party/forked/godep/doc.go
generated
vendored
Normal file
22
vendor/k8s.io/kubernetes/third_party/forked/godep/doc.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
|
||||
Command godep helps build packages reproducibly by fixing
|
||||
their dependencies.
|
||||
|
||||
Example Usage
|
||||
|
||||
Save currently-used dependencies to file Godeps:
|
||||
|
||||
$ godep save
|
||||
|
||||
Build project using saved dependencies:
|
||||
|
||||
$ godep go install
|
||||
|
||||
or
|
||||
|
||||
$ GOPATH=`godep path`:$GOPATH
|
||||
$ go install
|
||||
|
||||
*/
|
||||
package main
|
18
vendor/k8s.io/kubernetes/third_party/forked/godep/errors.go
generated
vendored
Normal file
18
vendor/k8s.io/kubernetes/third_party/forked/godep/errors.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
errorLoadingDeps = errors.New("error loading dependencies")
|
||||
errorLoadingPackages = errors.New("error loading packages")
|
||||
errorCopyingSourceCode = errors.New("error copying source code")
|
||||
errorNoPackagesUpdatable = errors.New("no packages can be updated")
|
||||
)
|
||||
|
||||
type errPackageNotFound struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func (e errPackageNotFound) Error() string {
|
||||
return "Package (" + e.path + ") not found"
|
||||
}
|
96
vendor/k8s.io/kubernetes/third_party/forked/godep/get.go
generated
vendored
Normal file
96
vendor/k8s.io/kubernetes/third_party/forked/godep/get.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
var cmdGet = &Command{
|
||||
Name: "get",
|
||||
Args: "[-t] [packages]",
|
||||
Short: "download and install packages with specified dependencies",
|
||||
Long: `
|
||||
Get downloads to GOPATH the packages named by the import paths, and installs
|
||||
them with the dependencies specified in their Godeps files.
|
||||
|
||||
If any of the packages do not have Godeps files, those are installed
|
||||
as if by go get.
|
||||
|
||||
If -t is given, dependencies of test files are also downloaded and installed.
|
||||
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
`,
|
||||
Run: runGet,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
var getT bool
|
||||
|
||||
func init() {
|
||||
cmdGet.Flag.BoolVar(&getT, "t", false, "get test dependencies")
|
||||
}
|
||||
|
||||
func runGet(cmd *Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
args = []string{"."}
|
||||
}
|
||||
|
||||
cmdArgs := []interface{}{"get", "-d"}
|
||||
if verbose {
|
||||
cmdArgs = append(cmdArgs, "-v")
|
||||
}
|
||||
|
||||
if getT {
|
||||
cmdArgs = append(cmdArgs, "-t")
|
||||
}
|
||||
|
||||
err := command("go", append(cmdArgs, args)...).Run()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
// group import paths by Godeps location
|
||||
groups := make(map[string][]string)
|
||||
ps, err := LoadPackages(args...)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
for _, pkg := range ps {
|
||||
if pkg.Error.Err != "" {
|
||||
log.Fatalln(pkg.Error.Err)
|
||||
}
|
||||
dir, _ := findInParents(pkg.Dir, "Godeps")
|
||||
groups[dir] = append(groups[dir], pkg.ImportPath)
|
||||
}
|
||||
for dir, packages := range groups {
|
||||
var c *exec.Cmd
|
||||
if dir == "" {
|
||||
c = command("go", "install", packages)
|
||||
} else {
|
||||
c = command("godep", "go", "install", packages)
|
||||
c.Dir = dir
|
||||
}
|
||||
if err := c.Run(); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// command is like exec.Command, but the returned
|
||||
// Cmd inherits stderr from the current process, and
|
||||
// elements of args may be either string or []string.
|
||||
func command(name string, args ...interface{}) *exec.Cmd {
|
||||
var a []string
|
||||
for _, arg := range args {
|
||||
switch v := arg.(type) {
|
||||
case string:
|
||||
a = append(a, v)
|
||||
case []string:
|
||||
a = append(a, v...)
|
||||
}
|
||||
}
|
||||
c := exec.Command(name, a...)
|
||||
c.Stderr = os.Stderr
|
||||
return c
|
||||
}
|
129
vendor/k8s.io/kubernetes/third_party/forked/godep/go.go
generated
vendored
Normal file
129
vendor/k8s.io/kubernetes/third_party/forked/godep/go.go
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var cmdGo = &Command{
|
||||
Name: "go",
|
||||
Args: "command [arguments]",
|
||||
Short: "run the go tool with saved dependencies",
|
||||
Long: `
|
||||
Go runs the go tool with a modified GOPATH giving access to
|
||||
dependencies saved in Godeps.
|
||||
|
||||
Any go tool command can run this way, but "godep go get"
|
||||
is unnecessary and has been disabled. Instead, use
|
||||
"godep go install".
|
||||
`,
|
||||
Run: runGo,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
// Find the godep GOPATH for this file tree and run the go tool.
|
||||
func runGo(cmd *Command, args []string) {
|
||||
gopath := prepareGopath()
|
||||
if s := os.Getenv("GOPATH"); s != "" {
|
||||
gopath += string(os.PathListSeparator) + os.Getenv("GOPATH")
|
||||
}
|
||||
if len(args) > 0 && args[0] == "get" {
|
||||
log.Printf("invalid subcommand: %q", "go get")
|
||||
fmt.Fprintln(os.Stderr, "Use 'godep go install' instead.")
|
||||
fmt.Fprintln(os.Stderr, "Run 'godep help go' for usage.")
|
||||
os.Exit(2)
|
||||
}
|
||||
c := exec.Command("go", args...)
|
||||
c.Env = append(envNoGopath(), "GOPATH="+gopath)
|
||||
c.Stdin = os.Stdin
|
||||
c.Stdout = os.Stdout
|
||||
c.Stderr = os.Stderr
|
||||
err := c.Run()
|
||||
if err != nil {
|
||||
log.Fatalln("go", err)
|
||||
}
|
||||
}
|
||||
|
||||
// prepareGopath reads dependency information from the filesystem
|
||||
// entry name, fetches any necessary code, and returns a gopath
|
||||
// causing the specified dependencies to be used.
|
||||
func prepareGopath() (gopath string) {
|
||||
dir, isDir := findGodeps()
|
||||
if dir == "" {
|
||||
log.Fatalln("No Godeps found (or in any parent directory)")
|
||||
}
|
||||
if !isDir {
|
||||
log.Fatalln(strings.TrimSpace(needSource))
|
||||
}
|
||||
return filepath.Join(dir, "Godeps", "_workspace")
|
||||
}
|
||||
|
||||
// findGodeps looks for a directory entry "Godeps" in the
|
||||
// current directory or any parent, and returns the containing
|
||||
// directory and whether the entry itself is a directory.
|
||||
// If Godeps can't be found, findGodeps returns "".
|
||||
// For any other error, it exits the program.
|
||||
func findGodeps() (dir string, isDir bool) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
return findInParents(wd, "Godeps")
|
||||
}
|
||||
|
||||
// isRoot returns true iff a path is a root.
|
||||
// On Unix: "/".
|
||||
// On Windows: "C:\", "D:\", ...
|
||||
func isRoot(p string) bool {
|
||||
p = filepath.Clean(p)
|
||||
volume := filepath.VolumeName(p)
|
||||
|
||||
p = strings.TrimPrefix(p, volume)
|
||||
p = filepath.ToSlash(p)
|
||||
|
||||
return p == "/"
|
||||
}
|
||||
|
||||
// findInParents returns the path to the directory containing name
|
||||
// in dir or any ancestor, and whether name itself is a directory.
|
||||
// If name cannot be found, findInParents returns the empty string.
|
||||
func findInParents(dir, name string) (container string, isDir bool) {
|
||||
for {
|
||||
fi, err := os.Stat(filepath.Join(dir, name))
|
||||
if os.IsNotExist(err) && isRoot(dir) {
|
||||
return "", false
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
dir = filepath.Dir(dir)
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
return dir, fi.IsDir()
|
||||
}
|
||||
}
|
||||
|
||||
func envNoGopath() (a []string) {
|
||||
for _, s := range os.Environ() {
|
||||
if !strings.HasPrefix(s, "GOPATH=") {
|
||||
a = append(a, s)
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
const needSource = `
|
||||
outdated Godeps missing source code
|
||||
|
||||
This dependency list was created with an old version of godep.
|
||||
|
||||
To work around this, you have two options:
|
||||
1. Run 'godep restore', and try again.
|
||||
2. Ask the maintainer to switch to a newer version of godep,
|
||||
then try again with the updated package.
|
||||
`
|
218
vendor/k8s.io/kubernetes/third_party/forked/godep/godepfile.go
generated
vendored
Normal file
218
vendor/k8s.io/kubernetes/third_party/forked/godep/godepfile.go
generated
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var (
|
||||
godepsFile = filepath.Join("Godeps", "Godeps.json")
|
||||
oldGodepsFile = filepath.Join("Godeps")
|
||||
)
|
||||
|
||||
// Godeps describes what a package needs to be rebuilt reproducibly.
|
||||
// It's the same information stored in file Godeps.
|
||||
type Godeps struct {
|
||||
ImportPath string
|
||||
GoVersion string
|
||||
GodepVersion string
|
||||
Packages []string `json:",omitempty"` // Arguments to save, if any.
|
||||
Deps []Dependency
|
||||
isOldFile bool
|
||||
}
|
||||
|
||||
func loadGodepsFile(path string) (Godeps, error) {
|
||||
var g Godeps
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return g, err
|
||||
}
|
||||
defer f.Close()
|
||||
err = json.NewDecoder(f).Decode(&g)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Unable to parse %s: %s", path, err.Error())
|
||||
}
|
||||
return g, err
|
||||
}
|
||||
|
||||
func loadDefaultGodepsFile() (Godeps, error) {
|
||||
var g Godeps
|
||||
var err error
|
||||
g, err = loadGodepsFile(godepsFile)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
var err1 error
|
||||
g, err1 = loadGodepsFile(oldGodepsFile)
|
||||
if err1 != nil {
|
||||
if os.IsNotExist(err1) {
|
||||
return g, err
|
||||
}
|
||||
return g, err1
|
||||
}
|
||||
g.isOldFile = true
|
||||
return g, nil
|
||||
}
|
||||
}
|
||||
return g, err
|
||||
}
|
||||
|
||||
// pkgs is the list of packages to read dependencies for
|
||||
func (g *Godeps) fill(pkgs []*Package, destImportPath string) error {
|
||||
debugln("fill", destImportPath)
|
||||
ppln(pkgs)
|
||||
var err1 error
|
||||
var path, testImports []string
|
||||
dipp := []string{destImportPath}
|
||||
for _, p := range pkgs {
|
||||
if p.Standard {
|
||||
log.Println("ignoring stdlib package:", p.ImportPath)
|
||||
continue
|
||||
}
|
||||
if p.Error.Err != "" {
|
||||
log.Println(p.Error.Err)
|
||||
err1 = errorLoadingPackages
|
||||
continue
|
||||
}
|
||||
path = append(path, p.ImportPath)
|
||||
path = append(path, p.Deps...)
|
||||
testImports = append(testImports, p.TestImports...)
|
||||
testImports = append(testImports, p.XTestImports...)
|
||||
}
|
||||
ps, err := LoadPackages(testImports...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, p := range ps {
|
||||
if p.Standard {
|
||||
continue
|
||||
}
|
||||
if p.Error.Err != "" {
|
||||
log.Println(p.Error.Err)
|
||||
err1 = errorLoadingPackages
|
||||
continue
|
||||
}
|
||||
path = append(path, p.ImportPath)
|
||||
path = append(path, p.Deps...)
|
||||
}
|
||||
debugln("path", path)
|
||||
for i, p := range path {
|
||||
path[i] = unqualify(p)
|
||||
}
|
||||
path = uniq(path)
|
||||
debugln("uniq, unqualify'd path", path)
|
||||
ps, err = LoadPackages(path...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, pkg := range ps {
|
||||
if pkg.Error.Err != "" {
|
||||
log.Println(pkg.Error.Err)
|
||||
err1 = errorLoadingDeps
|
||||
continue
|
||||
}
|
||||
if pkg.Standard || containsPathPrefix(dipp, pkg.ImportPath) {
|
||||
debugln("standard or dest skipping", pkg.ImportPath)
|
||||
continue
|
||||
}
|
||||
vcs, reporoot, err := VCSFromDir(pkg.Dir, filepath.Join(pkg.Root, "src"))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
err1 = errorLoadingDeps
|
||||
continue
|
||||
}
|
||||
id, err := vcs.identify(pkg.Dir)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
err1 = errorLoadingDeps
|
||||
continue
|
||||
}
|
||||
if vcs.isDirty(pkg.Dir, id) {
|
||||
log.Println("dirty working tree (please commit changes):", pkg.Dir)
|
||||
err1 = errorLoadingDeps
|
||||
continue
|
||||
}
|
||||
comment := vcs.describe(pkg.Dir, id)
|
||||
g.Deps = append(g.Deps, Dependency{
|
||||
ImportPath: pkg.ImportPath,
|
||||
Rev: id,
|
||||
Comment: comment,
|
||||
dir: pkg.Dir,
|
||||
ws: pkg.Root,
|
||||
root: filepath.ToSlash(reporoot),
|
||||
vcs: vcs,
|
||||
})
|
||||
}
|
||||
return err1
|
||||
}
|
||||
|
||||
func (g *Godeps) copy() *Godeps {
|
||||
h := *g
|
||||
h.Deps = make([]Dependency, len(g.Deps))
|
||||
copy(h.Deps, g.Deps)
|
||||
return &h
|
||||
}
|
||||
|
||||
func (g *Godeps) file() string {
|
||||
if g.isOldFile {
|
||||
return oldGodepsFile
|
||||
}
|
||||
return godepsFile
|
||||
}
|
||||
|
||||
func (g *Godeps) save() (int64, error) {
|
||||
f, err := os.Create(g.file())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer f.Close()
|
||||
return g.writeTo(f)
|
||||
}
|
||||
|
||||
func (g *Godeps) writeTo(w io.Writer) (int64, error) {
|
||||
g.GodepVersion = fmt.Sprintf("v%s", version) // godep always writes its current version.
|
||||
b, err := json.MarshalIndent(g, "", "\t")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
n, err := w.Write(append(b, '\n'))
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
func (g *Godeps) addOrUpdateDeps(deps []Dependency) {
|
||||
var missing []Dependency
|
||||
for _, d := range deps {
|
||||
var found bool
|
||||
for i := range g.Deps {
|
||||
if g.Deps[i].ImportPath == d.ImportPath {
|
||||
g.Deps[i] = d
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
missing = append(missing, d)
|
||||
}
|
||||
}
|
||||
g.Deps = append(g.Deps, missing...)
|
||||
}
|
||||
|
||||
func (g *Godeps) removeDeps(deps []Dependency) {
|
||||
var f []Dependency
|
||||
for i := range g.Deps {
|
||||
var found bool
|
||||
for _, d := range deps {
|
||||
if g.Deps[i].ImportPath == d.ImportPath {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
f = append(f, g.Deps[i])
|
||||
}
|
||||
}
|
||||
g.Deps = f
|
||||
}
|
59
vendor/k8s.io/kubernetes/third_party/forked/godep/license.go
generated
vendored
Normal file
59
vendor/k8s.io/kubernetes/third_party/forked/godep/license.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// LicenseFilePrefix is a list of filename prefixes that indicate it
|
||||
// might contain a software license
|
||||
var LicenseFilePrefix = []string{
|
||||
"licence", // UK spelling
|
||||
"license", // US spelling
|
||||
"copying",
|
||||
"unlicense",
|
||||
"copyright",
|
||||
"copyleft",
|
||||
"authors",
|
||||
"contributors",
|
||||
}
|
||||
|
||||
// LegalFileSubstring are substrings that indicate the file is likely
|
||||
// to contain some type of legal declaration. "legal" is often used
|
||||
// that it might moved to LicenseFilePrefix
|
||||
var LegalFileSubstring = []string{
|
||||
"legal",
|
||||
"notice",
|
||||
"disclaimer",
|
||||
"patent",
|
||||
"third-party",
|
||||
"thirdparty",
|
||||
}
|
||||
|
||||
// IsLicenseFile returns true if the filename might be contain a
|
||||
// software license
|
||||
func IsLicenseFile(filename string) bool {
|
||||
lowerfile := strings.ToLower(filename)
|
||||
for _, prefix := range LicenseFilePrefix {
|
||||
if strings.HasPrefix(lowerfile, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsLegalFile returns true if the file is likely to contain some type
|
||||
// of of legal declaration or licensing information
|
||||
func IsLegalFile(filename string) bool {
|
||||
lowerfile := strings.ToLower(filename)
|
||||
for _, prefix := range LicenseFilePrefix {
|
||||
if strings.HasPrefix(lowerfile, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, substring := range LegalFileSubstring {
|
||||
if strings.Contains(lowerfile, substring) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
601
vendor/k8s.io/kubernetes/third_party/forked/godep/list.go
generated
vendored
Normal file
601
vendor/k8s.io/kubernetes/third_party/forked/godep/list.go
generated
vendored
Normal file
@ -0,0 +1,601 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
pathpkg "path"
|
||||
)
|
||||
|
||||
var (
|
||||
gorootSrc = filepath.Join(build.Default.GOROOT, "src")
|
||||
ignoreTags = []string{"appengine", "ignore"} //TODO: appengine is a special case for now: https://github.com/tools/godep/issues/353
|
||||
versionMatch = regexp.MustCompile(`\Ago\d+\.\d+\z`)
|
||||
versionNegativeMatch = regexp.MustCompile(`\A\!go\d+\.\d+\z`)
|
||||
)
|
||||
|
||||
type errorMissingDep struct {
|
||||
i, dir string // import, dir
|
||||
}
|
||||
|
||||
func (e errorMissingDep) Error() string {
|
||||
return "Unable to find dependent package " + e.i + " in context of " + e.dir
|
||||
}
|
||||
|
||||
// packageContext is used to track an import and which package imported it.
|
||||
type packageContext struct {
|
||||
pkg *build.Package // package that imports the import
|
||||
imp string // import
|
||||
}
|
||||
|
||||
// depScanner tracks the processed and to be processed packageContexts
|
||||
type depScanner struct {
|
||||
processed []packageContext
|
||||
todo []packageContext
|
||||
}
|
||||
|
||||
// Next package and import to process
|
||||
func (ds *depScanner) Next() (*build.Package, string) {
|
||||
c := ds.todo[0]
|
||||
ds.processed = append(ds.processed, c)
|
||||
ds.todo = ds.todo[1:]
|
||||
return c.pkg, c.imp
|
||||
}
|
||||
|
||||
// Continue looping?
|
||||
func (ds *depScanner) Continue() bool {
|
||||
return len(ds.todo) > 0
|
||||
}
|
||||
|
||||
// Add a package and imports to the depScanner. Skips already processed/pending package/import combos
|
||||
func (ds *depScanner) Add(pkg *build.Package, imports ...string) {
|
||||
NextImport:
|
||||
for _, i := range imports {
|
||||
if i == "C" {
|
||||
i = "runtime/cgo"
|
||||
}
|
||||
for _, epc := range ds.processed {
|
||||
if pkg.Dir == epc.pkg.Dir && i == epc.imp {
|
||||
debugln("ctxts epc.pkg.Dir == pkg.Dir && i == epc.imp, skipping", epc.pkg.Dir, i)
|
||||
continue NextImport
|
||||
}
|
||||
}
|
||||
for _, epc := range ds.todo {
|
||||
if pkg.Dir == epc.pkg.Dir && i == epc.imp {
|
||||
debugln("ctxts epc.pkg.Dir == pkg.Dir && i == epc.imp, skipping", epc.pkg.Dir, i)
|
||||
continue NextImport
|
||||
}
|
||||
}
|
||||
pc := packageContext{pkg, i}
|
||||
debugln("Adding pc:", pc.pkg.Dir, pc.imp)
|
||||
ds.todo = append(ds.todo, pc)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
pkgCache = make(map[string]*build.Package) // dir => *build.Package
|
||||
)
|
||||
|
||||
// returns the package in dir either from a cache or by importing it and then caching it
|
||||
func fullPackageInDir(dir string) (*build.Package, error) {
|
||||
var err error
|
||||
pkg, ok := pkgCache[dir]
|
||||
if !ok {
|
||||
pkg, _ = build.ImportDir(dir, build.FindOnly)
|
||||
if pkg.Goroot {
|
||||
pkg, err = build.ImportDir(pkg.Dir, 0)
|
||||
} else {
|
||||
err = fillPackage(pkg)
|
||||
}
|
||||
if err == nil {
|
||||
pkgCache[dir] = pkg
|
||||
}
|
||||
}
|
||||
return pkg, err
|
||||
}
|
||||
|
||||
// listPackage specified by path
|
||||
func listPackage(path string) (*Package, error) {
|
||||
debugln("listPackage", path)
|
||||
var lp *build.Package
|
||||
dir, err := findDirForPath(path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lp, err = fullPackageInDir(dir)
|
||||
p := &Package{
|
||||
Dir: lp.Dir,
|
||||
Root: lp.Root,
|
||||
ImportPath: lp.ImportPath,
|
||||
XTestImports: lp.XTestImports,
|
||||
TestImports: lp.TestImports,
|
||||
GoFiles: lp.GoFiles,
|
||||
CgoFiles: lp.CgoFiles,
|
||||
TestGoFiles: lp.TestGoFiles,
|
||||
XTestGoFiles: lp.XTestGoFiles,
|
||||
IgnoredGoFiles: lp.IgnoredGoFiles,
|
||||
}
|
||||
p.Standard = lp.Goroot && lp.ImportPath != "" && !strings.Contains(lp.ImportPath, ".")
|
||||
if err != nil || p.Standard {
|
||||
return p, err
|
||||
}
|
||||
debugln("Looking For Package:", path, "in", dir)
|
||||
ppln(lp)
|
||||
|
||||
ds := depScanner{}
|
||||
ds.Add(lp, lp.Imports...)
|
||||
for ds.Continue() {
|
||||
ip, i := ds.Next()
|
||||
|
||||
debugf("Processing import %s for %s\n", i, ip.Dir)
|
||||
pdir, err := findDirForPath(i, ip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dp, err := fullPackageInDir(pdir)
|
||||
if err != nil { // This really should happen in this context though
|
||||
ppln(err)
|
||||
return nil, errorMissingDep{i: i, dir: ip.Dir}
|
||||
}
|
||||
ppln(dp)
|
||||
if !dp.Goroot {
|
||||
// Don't bother adding packages in GOROOT to the dependency scanner, they don't import things from outside of it.
|
||||
ds.Add(dp, dp.Imports...)
|
||||
}
|
||||
debugln("lp:")
|
||||
ppln(lp)
|
||||
debugln("ip:")
|
||||
ppln(ip)
|
||||
if lp == ip {
|
||||
debugln("lp == ip")
|
||||
p.Imports = append(p.Imports, dp.ImportPath)
|
||||
}
|
||||
p.Deps = append(p.Deps, dp.ImportPath)
|
||||
p.Dependencies = addDependency(p.Dependencies, dp)
|
||||
}
|
||||
p.Imports = uniq(p.Imports)
|
||||
p.Deps = uniq(p.Deps)
|
||||
debugln("Done Looking For Package:", path, "in", dir)
|
||||
ppln(p)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func addDependency(deps []build.Package, d *build.Package) []build.Package {
|
||||
for i := range deps {
|
||||
if deps[i].Dir == d.Dir {
|
||||
return deps
|
||||
}
|
||||
}
|
||||
return append(deps, *d)
|
||||
}
|
||||
|
||||
// finds the directory for the given import path in the context of the provided build.Package (if provided)
|
||||
func findDirForPath(path string, ip *build.Package) (string, error) {
|
||||
debugln("findDirForPath", path, ip)
|
||||
var search []string
|
||||
|
||||
if build.IsLocalImport(path) {
|
||||
dir := path
|
||||
if !filepath.IsAbs(dir) {
|
||||
if abs, err := filepath.Abs(dir); err == nil {
|
||||
// interpret relative to current directory
|
||||
dir = abs
|
||||
}
|
||||
}
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
// We need to check to see if the import exists in vendor/ folders up the hierarchy of the importing package
|
||||
if VendorExperiment && ip != nil {
|
||||
debugln("resolving vendor posibilities:", ip.Dir, ip.Root)
|
||||
cr := cleanPath(ip.Root)
|
||||
|
||||
for base := cleanPath(ip.Dir); !pathEqual(base, cr); base = cleanPath(filepath.Dir(base)) {
|
||||
s := filepath.Join(base, "vendor", path)
|
||||
debugln("Adding search dir:", s)
|
||||
search = append(search, s)
|
||||
}
|
||||
}
|
||||
|
||||
for _, base := range build.Default.SrcDirs() {
|
||||
search = append(search, filepath.Join(base, path))
|
||||
}
|
||||
|
||||
for _, dir := range search {
|
||||
debugln("searching", dir)
|
||||
fi, err := stat(dir)
|
||||
if err == nil && fi.IsDir() {
|
||||
return dir, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errPackageNotFound{path}
|
||||
}
|
||||
|
||||
type statEntry struct {
|
||||
fi os.FileInfo
|
||||
err error
|
||||
}
|
||||
|
||||
var (
|
||||
statCache = make(map[string]statEntry)
|
||||
)
|
||||
|
||||
func clearStatCache() {
|
||||
statCache = make(map[string]statEntry)
|
||||
}
|
||||
|
||||
func stat(p string) (os.FileInfo, error) {
|
||||
if e, ok := statCache[p]; ok {
|
||||
return e.fi, e.err
|
||||
}
|
||||
fi, err := os.Stat(p)
|
||||
statCache[p] = statEntry{fi, err}
|
||||
return fi, err
|
||||
}
|
||||
|
||||
// fillPackage full of info. Assumes p.Dir is set at a minimum
|
||||
func fillPackage(p *build.Package) error {
|
||||
if p.Goroot {
|
||||
return nil
|
||||
}
|
||||
|
||||
if p.SrcRoot == "" {
|
||||
for _, base := range build.Default.SrcDirs() {
|
||||
if strings.HasPrefix(p.Dir, base) {
|
||||
p.SrcRoot = base
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if p.SrcRoot == "" {
|
||||
return errors.New("Unable to find SrcRoot for package " + p.ImportPath)
|
||||
}
|
||||
|
||||
if p.Root == "" {
|
||||
p.Root = filepath.Dir(p.SrcRoot)
|
||||
}
|
||||
|
||||
var buildMatch = "+build "
|
||||
var buildFieldSplit = func(r rune) bool {
|
||||
return unicode.IsSpace(r) || r == ','
|
||||
}
|
||||
|
||||
debugln("Filling package:", p.ImportPath, "from", p.Dir)
|
||||
gofiles, err := filepath.Glob(filepath.Join(p.Dir, "*.go"))
|
||||
if err != nil {
|
||||
debugln("Error globbing", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if len(gofiles) == 0 {
|
||||
return &build.NoGoError{Dir: p.Dir}
|
||||
}
|
||||
|
||||
var testImports []string
|
||||
var imports []string
|
||||
NextFile:
|
||||
for _, file := range gofiles {
|
||||
debugln(file)
|
||||
pf, err := parser.ParseFile(token.NewFileSet(), file, nil, parser.ImportsOnly|parser.ParseComments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
testFile := strings.HasSuffix(file, "_test.go")
|
||||
fname := filepath.Base(file)
|
||||
for _, c := range pf.Comments {
|
||||
ct := c.Text()
|
||||
if i := strings.Index(ct, buildMatch); i != -1 {
|
||||
for _, t := range strings.FieldsFunc(ct[i+len(buildMatch):], buildFieldSplit) {
|
||||
for _, tag := range ignoreTags {
|
||||
if t == tag {
|
||||
p.IgnoredGoFiles = append(p.IgnoredGoFiles, fname)
|
||||
continue NextFile
|
||||
}
|
||||
}
|
||||
|
||||
if versionMatch.MatchString(t) && !isSameOrNewer(t, majorGoVersion) {
|
||||
debugln("Adding", fname, "to ignored list because of version tag", t)
|
||||
p.IgnoredGoFiles = append(p.IgnoredGoFiles, fname)
|
||||
continue NextFile
|
||||
}
|
||||
if versionNegativeMatch.MatchString(t) && isSameOrNewer(t[1:], majorGoVersion) {
|
||||
debugln("Adding", fname, "to ignored list because of version tag", t)
|
||||
p.IgnoredGoFiles = append(p.IgnoredGoFiles, fname)
|
||||
continue NextFile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if testFile {
|
||||
p.TestGoFiles = append(p.TestGoFiles, fname)
|
||||
} else {
|
||||
p.GoFiles = append(p.GoFiles, fname)
|
||||
}
|
||||
for _, is := range pf.Imports {
|
||||
name, err := strconv.Unquote(is.Path.Value)
|
||||
if err != nil {
|
||||
return err // can't happen?
|
||||
}
|
||||
if testFile {
|
||||
testImports = append(testImports, name)
|
||||
} else {
|
||||
imports = append(imports, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
imports = uniq(imports)
|
||||
testImports = uniq(testImports)
|
||||
p.Imports = imports
|
||||
p.TestImports = testImports
|
||||
return nil
|
||||
}
|
||||
|
||||
// All of the following functions were vendored from go proper. Locations are noted in comments, but may change in future Go versions.
|
||||
|
||||
// importPaths returns the import paths to use for the given command line.
|
||||
// $GOROOT/src/cmd/main.go:366
|
||||
func importPaths(args []string) []string {
|
||||
debugf("importPathsNoDotExpansion(%q) == ", args)
|
||||
args = importPathsNoDotExpansion(args)
|
||||
debugf("%q\n", args)
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
if strings.Contains(a, "...") {
|
||||
if build.IsLocalImport(a) {
|
||||
debugf("build.IsLocalImport(%q) == true\n", a)
|
||||
pkgs := allPackagesInFS(a)
|
||||
debugf("allPackagesInFS(%q) == %q\n", a, pkgs)
|
||||
out = append(out, pkgs...)
|
||||
} else {
|
||||
debugf("build.IsLocalImport(%q) == false\n", a)
|
||||
pkgs := allPackages(a)
|
||||
debugf("allPackages(%q) == %q\n", a, pkgs)
|
||||
out = append(out, allPackages(a)...)
|
||||
}
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// importPathsNoDotExpansion returns the import paths to use for the given
|
||||
// command line, but it does no ... expansion.
|
||||
// $GOROOT/src/cmd/main.go:332
|
||||
func importPathsNoDotExpansion(args []string) []string {
|
||||
if len(args) == 0 {
|
||||
return []string{"."}
|
||||
}
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
// Arguments are supposed to be import paths, but
|
||||
// as a courtesy to Windows developers, rewrite \ to /
|
||||
// in command-line arguments. Handles .\... and so on.
|
||||
if filepath.Separator == '\\' {
|
||||
a = strings.Replace(a, `\`, `/`, -1)
|
||||
}
|
||||
|
||||
// Put argument in canonical form, but preserve leading ./.
|
||||
if strings.HasPrefix(a, "./") {
|
||||
a = "./" + pathpkg.Clean(a)
|
||||
if a == "./." {
|
||||
a = "."
|
||||
}
|
||||
} else {
|
||||
a = pathpkg.Clean(a)
|
||||
}
|
||||
if a == "all" || a == "std" || a == "cmd" {
|
||||
out = append(out, allPackages(a)...)
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// allPackagesInFS is like allPackages but is passed a pattern
|
||||
// beginning ./ or ../, meaning it should scan the tree rooted
|
||||
// at the given directory. There are ... in the pattern too.
|
||||
// $GOROOT/src/cmd/main.go:620
|
||||
func allPackagesInFS(pattern string) []string {
|
||||
pkgs := matchPackagesInFS(pattern)
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// allPackages returns all the packages that can be found
|
||||
// under the $GOPATH directories and $GOROOT matching pattern.
|
||||
// The pattern is either "all" (all packages), "std" (standard packages),
|
||||
// "cmd" (standard commands), or a path including "...".
|
||||
// $GOROOT/src/cmd/main.go:542
|
||||
func allPackages(pattern string) []string {
|
||||
pkgs := matchPackages(pattern)
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// $GOROOT/src/cmd/main.go:554
|
||||
// This has been changed to not use build.ImportDir
|
||||
func matchPackages(pattern string) []string {
|
||||
match := func(string) bool { return true }
|
||||
treeCanMatch := func(string) bool { return true }
|
||||
if pattern != "all" && pattern != "std" && pattern != "cmd" {
|
||||
match = matchPattern(pattern)
|
||||
treeCanMatch = treeCanMatchPattern(pattern)
|
||||
}
|
||||
|
||||
have := map[string]bool{
|
||||
"builtin": true, // ignore pseudo-package that exists only for documentation
|
||||
}
|
||||
if !build.Default.CgoEnabled {
|
||||
have["runtime/cgo"] = true // ignore during walk
|
||||
}
|
||||
var pkgs []string
|
||||
|
||||
for _, src := range build.Default.SrcDirs() {
|
||||
if (pattern == "std" || pattern == "cmd") && src != gorootSrc {
|
||||
continue
|
||||
}
|
||||
src = filepath.Clean(src) + string(filepath.Separator)
|
||||
root := src
|
||||
if pattern == "cmd" {
|
||||
root += "cmd" + string(filepath.Separator)
|
||||
}
|
||||
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() || path == src {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Avoid .foo, _foo, and testdata directory trees.
|
||||
_, elem := filepath.Split(path)
|
||||
if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
name := filepath.ToSlash(path[len(src):])
|
||||
if pattern == "std" && (strings.Contains(name, ".") || name == "cmd") {
|
||||
// The name "std" is only the standard library.
|
||||
// If the name has a dot, assume it's a domain name for go get,
|
||||
// and if the name is cmd, it's the root of the command tree.
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if !treeCanMatch(name) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if have[name] {
|
||||
return nil
|
||||
}
|
||||
have[name] = true
|
||||
if !match(name) {
|
||||
return nil
|
||||
}
|
||||
|
||||
ap, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if _, err = fullPackageInDir(ap); err != nil {
|
||||
debugf("matchPackage(%q) ap=%q Error: %q\n", ap, pattern, err)
|
||||
if _, noGo := err.(*build.NoGoError); noGo {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
pkgs = append(pkgs, name)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// treeCanMatchPattern(pattern)(name) reports whether
|
||||
// name or children of name can possibly match pattern.
|
||||
// Pattern is the same limited glob accepted by matchPattern.
|
||||
// $GOROOT/src/cmd/main.go:527
|
||||
func treeCanMatchPattern(pattern string) func(name string) bool {
|
||||
wildCard := false
|
||||
if i := strings.Index(pattern, "..."); i >= 0 {
|
||||
wildCard = true
|
||||
pattern = pattern[:i]
|
||||
}
|
||||
return func(name string) bool {
|
||||
return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
|
||||
wildCard && strings.HasPrefix(name, pattern)
|
||||
}
|
||||
}
|
||||
|
||||
// hasPathPrefix reports whether the path s begins with the
|
||||
// elements in prefix.
|
||||
// $GOROOT/src/cmd/main.go:489
|
||||
func hasPathPrefix(s, prefix string) bool {
|
||||
switch {
|
||||
default:
|
||||
return false
|
||||
case len(s) == len(prefix):
|
||||
return s == prefix
|
||||
case len(s) > len(prefix):
|
||||
if prefix != "" && prefix[len(prefix)-1] == '/' {
|
||||
return strings.HasPrefix(s, prefix)
|
||||
}
|
||||
return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
|
||||
}
|
||||
}
|
||||
|
||||
// $GOROOT/src/cmd/go/main.go:631
|
||||
// This has been changed to not use build.ImportDir
|
||||
func matchPackagesInFS(pattern string) []string {
|
||||
// Find directory to begin the scan.
|
||||
// Could be smarter but this one optimization
|
||||
// is enough for now, since ... is usually at the
|
||||
// end of a path.
|
||||
i := strings.Index(pattern, "...")
|
||||
dir, _ := pathpkg.Split(pattern[:i])
|
||||
|
||||
// pattern begins with ./ or ../.
|
||||
// path.Clean will discard the ./ but not the ../.
|
||||
// We need to preserve the ./ for pattern matching
|
||||
// and in the returned import paths.
|
||||
prefix := ""
|
||||
if strings.HasPrefix(pattern, "./") {
|
||||
prefix = "./"
|
||||
}
|
||||
match := matchPattern(pattern)
|
||||
|
||||
var pkgs []string
|
||||
filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if path == dir {
|
||||
// filepath.Walk starts at dir and recurses. For the recursive case,
|
||||
// the path is the result of filepath.Join, which calls filepath.Clean.
|
||||
// The initial case is not Cleaned, though, so we do this explicitly.
|
||||
//
|
||||
// This converts a path like "./io/" to "io". Without this step, running
|
||||
// "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io
|
||||
// package, because prepending the prefix "./" to the unclean path would
|
||||
// result in "././io", and match("././io") returns false.
|
||||
path = filepath.Clean(path)
|
||||
}
|
||||
|
||||
// Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
|
||||
_, elem := filepath.Split(path)
|
||||
dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
|
||||
if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
name := prefix + filepath.ToSlash(path)
|
||||
if !match(name) {
|
||||
return nil
|
||||
}
|
||||
ap, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if _, err = fullPackageInDir(ap); err != nil {
|
||||
debugf("matchPackageInFS(%q) ap=%q Error: %q\n", ap, pattern, err)
|
||||
if _, noGo := err.(*build.NoGoError); !noGo {
|
||||
log.Print(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
pkgs = append(pkgs, name)
|
||||
return nil
|
||||
})
|
||||
return pkgs
|
||||
}
|
255
vendor/k8s.io/kubernetes/third_party/forked/godep/main.go
generated
vendored
Normal file
255
vendor/k8s.io/kubernetes/third_party/forked/godep/main.go
generated
vendored
Normal file
@ -0,0 +1,255 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var (
|
||||
cpuprofile string
|
||||
verbose bool // Verbose flag for commands that support it
|
||||
debug bool // Debug flag for commands that support it
|
||||
majorGoVersion string
|
||||
VendorExperiment bool
|
||||
sep string
|
||||
)
|
||||
|
||||
// Command is an implementation of a godep command
|
||||
// like godep save or godep go.
|
||||
type Command struct {
|
||||
// Run runs the command.
|
||||
// The args are the arguments after the command name.
|
||||
Run func(cmd *Command, args []string)
|
||||
|
||||
// Name of the command
|
||||
Name string
|
||||
|
||||
// Args the command would expect
|
||||
Args string
|
||||
|
||||
// Short is the short description shown in the 'godep help' output.
|
||||
Short string
|
||||
|
||||
// Long is the long message shown in the
|
||||
// 'godep help <this-command>' output.
|
||||
Long string
|
||||
|
||||
// Flag is a set of flags specific to this command.
|
||||
Flag flag.FlagSet
|
||||
|
||||
// OnlyInGOPATH limits this command to being run only while inside of a GOPATH
|
||||
OnlyInGOPATH bool
|
||||
}
|
||||
|
||||
// UsageExit prints usage information and exits.
|
||||
func (c *Command) UsageExit() {
|
||||
fmt.Fprintf(os.Stderr, "Args: godep %s [-v] [-d] %s\n\n", c.Name, c.Args)
|
||||
fmt.Fprintf(os.Stderr, "Run 'godep help %s' for help.\n", c.Name)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// Commands lists the available commands and help topics.
|
||||
// The order here is the order in which they are printed
|
||||
// by 'godep help'.
|
||||
var commands = []*Command{
|
||||
cmdSave,
|
||||
cmdGo,
|
||||
cmdGet,
|
||||
cmdPath,
|
||||
cmdRestore,
|
||||
cmdUpdate,
|
||||
cmdDiff,
|
||||
cmdVersion,
|
||||
}
|
||||
|
||||
// VendorExperiment is the Go 1.5 vendor directory experiment flag, see
|
||||
// https://github.com/golang/go/commit/183cc0cd41f06f83cb7a2490a499e3f9101befff
|
||||
// Honor the env var unless the project already has an old school godep workspace
|
||||
func determineVendor(v string) bool {
|
||||
go15ve := os.Getenv("GO15VENDOREXPERIMENT")
|
||||
var ev bool
|
||||
switch v {
|
||||
case "go1", "go1.1", "go1.2", "go1.3", "go1.4":
|
||||
ev = false
|
||||
case "go1.5":
|
||||
ev = go15ve == "1"
|
||||
case "go1.6":
|
||||
ev = go15ve != "0"
|
||||
default: //go1.7+, devel*
|
||||
ev = true
|
||||
}
|
||||
|
||||
ws := filepath.Join("Godeps", "_workspace")
|
||||
s, err := os.Stat(ws)
|
||||
if err == nil && s.IsDir() {
|
||||
log.Printf("WARNING: Godep workspaces (./Godeps/_workspace) are deprecated and support for them will be removed when go1.8 is released.")
|
||||
if ev {
|
||||
log.Printf("WARNING: Go version (%s) & $GO15VENDOREXPERIMENT=%s wants to enable the vendor experiment, but disabling because a Godep workspace (%s) exists\n", v, go15ve, ws)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return ev
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("godep: ")
|
||||
log.SetOutput(os.Stderr)
|
||||
|
||||
flag.Usage = usageExit
|
||||
flag.Parse()
|
||||
args := flag.Args()
|
||||
if len(args) < 1 {
|
||||
usageExit()
|
||||
}
|
||||
|
||||
if args[0] == "help" {
|
||||
help(args[1:])
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
majorGoVersion, err = goVersion()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name == args[0] {
|
||||
if cmd.OnlyInGOPATH {
|
||||
checkInGOPATH()
|
||||
}
|
||||
|
||||
VendorExperiment = determineVendor(majorGoVersion)
|
||||
// sep is the signature set of path elements that
|
||||
// precede the original path of an imported package.
|
||||
sep = defaultSep(VendorExperiment)
|
||||
|
||||
cmd.Flag.BoolVar(&verbose, "v", false, "enable verbose output")
|
||||
cmd.Flag.BoolVar(&debug, "d", false, "enable debug output")
|
||||
cmd.Flag.StringVar(&cpuprofile, "cpuprofile", "", "Write cpu profile to this file")
|
||||
cmd.Flag.Usage = func() { cmd.UsageExit() }
|
||||
cmd.Flag.Parse(args[1:])
|
||||
|
||||
debugln("versionString()", versionString())
|
||||
debugln("majorGoVersion", majorGoVersion)
|
||||
debugln("VendorExperiment", VendorExperiment)
|
||||
debugln("sep", sep)
|
||||
|
||||
if cpuprofile != "" {
|
||||
f, err := os.Create(cpuprofile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
pprof.StartCPUProfile(f)
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
cmd.Run(cmd, cmd.Flag.Args())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "godep: unknown command %q\n", args[0])
|
||||
fmt.Fprintf(os.Stderr, "Run 'godep help' for usage.\n")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func subPath(sub, path string) bool {
|
||||
ls := strings.ToLower(sub)
|
||||
lp := strings.ToLower(path)
|
||||
if ls == lp {
|
||||
return false
|
||||
}
|
||||
return strings.HasPrefix(ls, lp)
|
||||
}
|
||||
|
||||
func checkInGOPATH() {
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal("Unable to determine current working directory", err)
|
||||
}
|
||||
dirs := build.Default.SrcDirs()
|
||||
for _, p := range dirs {
|
||||
if ok := subPath(pwd, p); ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("[WARNING]: godep should only be used inside a valid go package directory and")
|
||||
log.Println("[WARNING]: may not function correctly. You are probably outside of your $GOPATH.")
|
||||
log.Printf("[WARNING]:\tCurrent Directory: %s\n", pwd)
|
||||
log.Printf("[WARNING]:\t$GOPATH: %s\n", os.Getenv("GOPATH"))
|
||||
}
|
||||
|
||||
var usageTemplate = `
|
||||
Godep is a tool for managing Go package dependencies.
|
||||
|
||||
Usage:
|
||||
|
||||
godep command [arguments]
|
||||
|
||||
The commands are:
|
||||
{{range .}}
|
||||
{{.Name | printf "%-8s"}} {{.Short}}{{end}}
|
||||
|
||||
Use "godep help [command]" for more information about a command.
|
||||
`
|
||||
|
||||
var helpTemplate = `
|
||||
Args: godep {{.Name}} [-v] [-d] {{.Args}}
|
||||
|
||||
{{.Long | trim}}
|
||||
|
||||
If -v is given, verbose output is enabled.
|
||||
|
||||
If -d is given, debug output is enabled (you probably don't want this, see -v).
|
||||
|
||||
`
|
||||
|
||||
func help(args []string) {
|
||||
if len(args) == 0 {
|
||||
printUsage(os.Stdout)
|
||||
return
|
||||
}
|
||||
if len(args) != 1 {
|
||||
fmt.Fprintf(os.Stderr, "usage: godep help command\n\n")
|
||||
fmt.Fprintf(os.Stderr, "Too many arguments given.\n")
|
||||
os.Exit(2)
|
||||
}
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name == args[0] {
|
||||
tmpl(os.Stdout, helpTemplate, cmd)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func usageExit() {
|
||||
printUsage(os.Stderr)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func printUsage(w io.Writer) {
|
||||
tmpl(w, usageTemplate, commands)
|
||||
}
|
||||
|
||||
// tmpl executes the given template text on data, writing the result to w.
|
||||
func tmpl(w io.Writer, text string, data interface{}) {
|
||||
t := template.New("top")
|
||||
t.Funcs(template.FuncMap{
|
||||
"trim": strings.TrimSpace,
|
||||
})
|
||||
template.Must(t.Parse(strings.TrimSpace(text) + "\n\n"))
|
||||
if err := t.Execute(w, data); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
35
vendor/k8s.io/kubernetes/third_party/forked/godep/msg.go
generated
vendored
Normal file
35
vendor/k8s.io/kubernetes/third_party/forked/godep/msg.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/kr/pretty"
|
||||
)
|
||||
|
||||
func debugln(a ...interface{}) (int, error) {
|
||||
if debug {
|
||||
return fmt.Println(a...)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func verboseln(a ...interface{}) {
|
||||
if verbose {
|
||||
log.Println(a...)
|
||||
}
|
||||
}
|
||||
|
||||
func debugf(format string, a ...interface{}) (int, error) {
|
||||
if debug {
|
||||
return fmt.Printf(format, a...)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func ppln(a ...interface{}) (int, error) {
|
||||
if debug {
|
||||
return pretty.Println(a...)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
36
vendor/k8s.io/kubernetes/third_party/forked/godep/path.go
generated
vendored
Normal file
36
vendor/k8s.io/kubernetes/third_party/forked/godep/path.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var cmdPath = &Command{
|
||||
Name: "path",
|
||||
Short: "print GOPATH for dependency code",
|
||||
Long: `
|
||||
Command path prints a path for use in env var GOPATH
|
||||
that makes available the specified version of each dependency.
|
||||
|
||||
The printed path does not include any GOPATH value from
|
||||
the environment.
|
||||
|
||||
For more about how GOPATH works, see 'go help gopath'.
|
||||
`,
|
||||
Run: runPath,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
// Print the gopath that points to
|
||||
// the included dependency code.
|
||||
func runPath(cmd *Command, args []string) {
|
||||
if len(args) != 0 {
|
||||
cmd.UsageExit()
|
||||
}
|
||||
if VendorExperiment {
|
||||
fmt.Fprintln(os.Stderr, "Error: GO15VENDOREXPERIMENT is enabled and the vendor/ directory is not a valid Go workspace.")
|
||||
os.Exit(1)
|
||||
}
|
||||
gopath := prepareGopath()
|
||||
fmt.Println(gopath)
|
||||
}
|
81
vendor/k8s.io/kubernetes/third_party/forked/godep/pkg.go
generated
vendored
Normal file
81
vendor/k8s.io/kubernetes/third_party/forked/godep/pkg.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/build"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Package represents a Go package.
|
||||
type Package struct {
|
||||
Dir string
|
||||
Root string
|
||||
ImportPath string
|
||||
Deps []string
|
||||
Standard bool
|
||||
Processed bool
|
||||
|
||||
GoFiles []string
|
||||
CgoFiles []string
|
||||
IgnoredGoFiles []string
|
||||
|
||||
TestGoFiles []string
|
||||
TestImports []string
|
||||
XTestGoFiles []string
|
||||
XTestImports []string
|
||||
|
||||
Error struct {
|
||||
Err string
|
||||
}
|
||||
|
||||
// --- New stuff for now
|
||||
Imports []string
|
||||
Dependencies []build.Package
|
||||
}
|
||||
|
||||
// LoadPackages loads the named packages
|
||||
// Unlike the go tool, an empty argument list is treated as an empty list; "."
|
||||
// must be given explicitly if desired.
|
||||
// IgnoredGoFiles will be processed and their dependencies resolved recursively
|
||||
func LoadPackages(names ...string) (a []*Package, err error) {
|
||||
debugln("LoadPackages", names)
|
||||
if len(names) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
for _, i := range importPaths(names) {
|
||||
p, err := listPackage(i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a = append(a, p)
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (p *Package) allGoFiles() []string {
|
||||
var a []string
|
||||
a = append(a, p.GoFiles...)
|
||||
a = append(a, p.CgoFiles...)
|
||||
a = append(a, p.TestGoFiles...)
|
||||
a = append(a, p.XTestGoFiles...)
|
||||
a = append(a, p.IgnoredGoFiles...)
|
||||
return a
|
||||
}
|
||||
|
||||
// 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.
|
||||
// Taken from $GOROOT/src/cmd/go/main.go.
|
||||
func matchPattern(pattern string) func(name string) bool {
|
||||
re := regexp.QuoteMeta(pattern)
|
||||
re = strings.Replace(re, `\.\.\.`, `.*`, -1)
|
||||
// Special case: foo/... matches foo too.
|
||||
if strings.HasSuffix(re, `/.*`) {
|
||||
re = re[:len(re)-len(`/.*`)] + `(/.*)?`
|
||||
}
|
||||
reg := regexp.MustCompile(`^` + re + `$`)
|
||||
return func(name string) bool {
|
||||
return reg.MatchString(name)
|
||||
}
|
||||
}
|
195
vendor/k8s.io/kubernetes/third_party/forked/godep/restore.go
generated
vendored
Normal file
195
vendor/k8s.io/kubernetes/third_party/forked/godep/restore.go
generated
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"go/build"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/tools/go/vcs"
|
||||
)
|
||||
|
||||
var cmdRestore = &Command{
|
||||
Name: "restore",
|
||||
Short: "check out listed dependency versions in GOPATH",
|
||||
Long: `
|
||||
Restore checks out the Godeps-specified version of each package in GOPATH.
|
||||
|
||||
NOTE: restore leaves git repositories in a detached state. go1.6+ no longer
|
||||
checks out the master branch when doing a "go get", see:
|
||||
https://github.com/golang/go/commit/42206598671a44111c8f726ad33dc7b265bdf669.
|
||||
|
||||
`,
|
||||
Run: runRestore,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
// Three phases:
|
||||
// 1. Download all deps
|
||||
// 2. Restore all deps (checkout the recorded rev)
|
||||
// 3. Attempt to load all deps as a simple consistency check
|
||||
func runRestore(cmd *Command, args []string) {
|
||||
if len(build.Default.GOPATH) == 0 {
|
||||
log.Println("Error restore requires GOPATH but it is empty.")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var hadError bool
|
||||
checkErr := func(s string) {
|
||||
if hadError {
|
||||
log.Println(s)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
g, err := loadDefaultGodepsFile()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
for i, dep := range g.Deps {
|
||||
verboseln("Downloading dependency (if needed):", dep.ImportPath)
|
||||
err := download(&dep)
|
||||
if err != nil {
|
||||
log.Printf("error downloading dep (%s): %s\n", dep.ImportPath, err)
|
||||
hadError = true
|
||||
}
|
||||
g.Deps[i] = dep
|
||||
}
|
||||
checkErr("Error downloading some deps. Aborting restore and check.")
|
||||
for _, dep := range g.Deps {
|
||||
verboseln("Restoring dependency (if needed):", dep.ImportPath)
|
||||
err := restore(dep)
|
||||
if err != nil {
|
||||
log.Printf("error restoring dep (%s): %s\n", dep.ImportPath, err)
|
||||
hadError = true
|
||||
}
|
||||
}
|
||||
checkErr("Error restoring some deps. Aborting check.")
|
||||
for _, dep := range g.Deps {
|
||||
verboseln("Checking dependency:", dep.ImportPath)
|
||||
_, err := LoadPackages(dep.ImportPath)
|
||||
if err != nil {
|
||||
log.Printf("Dep (%s) restored, but was unable to load it with error:\n\t%s\n", dep.ImportPath, err)
|
||||
if me, ok := err.(errorMissingDep); ok {
|
||||
log.Println("\tThis may be because the dependencies were saved with an older version of godep (< v33).")
|
||||
log.Printf("\tTry `go get %s`. Then `godep save` to update deps.\n", me.i)
|
||||
}
|
||||
hadError = true
|
||||
}
|
||||
}
|
||||
checkErr("Error checking some deps.")
|
||||
}
|
||||
|
||||
var downloaded = make(map[string]bool)
|
||||
|
||||
// download the given dependency.
|
||||
// 2 Passes: 1) go get -d <pkg>, 2) git pull (if necessary)
|
||||
func download(dep *Dependency) error {
|
||||
|
||||
rr, err := vcs.RepoRootForImportPath(dep.ImportPath, debug)
|
||||
if err != nil {
|
||||
debugln("Error determining repo root for", dep.ImportPath)
|
||||
return err
|
||||
}
|
||||
ppln("rr", rr)
|
||||
|
||||
dep.vcs = cmd[rr.VCS]
|
||||
|
||||
// try to find an existing directory in the GOPATHs
|
||||
for _, gp := range filepath.SplitList(build.Default.GOPATH) {
|
||||
t := filepath.Join(gp, "src", rr.Root)
|
||||
fi, err := os.Stat(t)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if fi.IsDir() {
|
||||
dep.root = t
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If none found, just pick the first GOPATH entry (AFAICT that's what go get does)
|
||||
if dep.root == "" {
|
||||
dep.root = filepath.Join(filepath.SplitList(build.Default.GOPATH)[0], "src", rr.Root)
|
||||
}
|
||||
ppln("dep", dep)
|
||||
|
||||
if downloaded[rr.Repo] {
|
||||
verboseln("Skipping already downloaded repo", rr.Repo)
|
||||
return nil
|
||||
}
|
||||
|
||||
fi, err := os.Stat(dep.root)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(filepath.Dir(dep.root), os.ModePerm); err != nil {
|
||||
debugln("Error creating base dir of", dep.root)
|
||||
return err
|
||||
}
|
||||
err := rr.VCS.CreateAtRev(dep.root, rr.Repo, dep.Rev)
|
||||
debugln("CreatedAtRev", dep.root, rr.Repo, dep.Rev)
|
||||
if err != nil {
|
||||
debugln("CreateAtRev error", err)
|
||||
return err
|
||||
}
|
||||
downloaded[rr.Repo] = true
|
||||
return nil
|
||||
}
|
||||
debugln("Error checking repo root for", dep.ImportPath, "at", dep.root, ":", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if !fi.IsDir() {
|
||||
return errors.New("repo root src dir exists, but isn't a directory for " + dep.ImportPath + " at " + dep.root)
|
||||
}
|
||||
|
||||
if !dep.vcs.exists(dep.root, dep.Rev) {
|
||||
debugln("Updating existing", dep.root)
|
||||
if dep.vcs == vcsGit {
|
||||
detached, err := gitDetached(dep.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if detached {
|
||||
db, err := gitDefaultBranch(dep.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := gitCheckout(dep.root, db); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dep.vcs.vcs.Download(dep.root)
|
||||
downloaded[rr.Repo] = true
|
||||
}
|
||||
|
||||
debugln("Nothing to download")
|
||||
return nil
|
||||
}
|
||||
|
||||
var restored = make(map[string]string) // dep.root -> dep.Rev
|
||||
|
||||
// restore checks out the given revision.
|
||||
func restore(dep Dependency) error {
|
||||
rev, ok := restored[dep.root]
|
||||
debugln(rev)
|
||||
debugln(ok)
|
||||
debugln(dep.root)
|
||||
if ok {
|
||||
if rev != dep.Rev {
|
||||
return errors.New("Wanted to restore rev " + dep.Rev + ", already restored rev " + rev + " for another package in the repo")
|
||||
}
|
||||
verboseln("Skipping already restored repo")
|
||||
return nil
|
||||
}
|
||||
|
||||
debugln("Restoring:", dep.ImportPath, dep.Rev)
|
||||
err := dep.vcs.RevSync(dep.root, dep.Rev)
|
||||
if err == nil {
|
||||
restored[dep.root] = dep.Rev
|
||||
}
|
||||
return err
|
||||
}
|
171
vendor/k8s.io/kubernetes/third_party/forked/godep/rewrite.go
generated
vendored
Normal file
171
vendor/k8s.io/kubernetes/third_party/forked/godep/rewrite.go
generated
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
|
||||
"github.com/kr/fs"
|
||||
)
|
||||
|
||||
// rewrite visits the go files in pkgs, plus all go files
|
||||
// in the directory tree Godeps, rewriting import statements
|
||||
// according to the rules for func qualify.
|
||||
func rewrite(pkgs []*Package, qual string, paths []string) error {
|
||||
for _, path := range pkgFiles(pkgs) {
|
||||
debugln("rewrite", path)
|
||||
err := rewriteTree(path, qual, paths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return rewriteTree("Godeps", qual, paths)
|
||||
}
|
||||
|
||||
// pkgFiles returns the full filesystem path to all go files in pkgs.
|
||||
func pkgFiles(pkgs []*Package) []string {
|
||||
var a []string
|
||||
for _, pkg := range pkgs {
|
||||
for _, s := range pkg.allGoFiles() {
|
||||
a = append(a, filepath.Join(pkg.Dir, s))
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// rewriteTree recursively visits the go files in path, rewriting
|
||||
// import statements according to the rules for func qualify.
|
||||
// This function ignores the 'testdata' directory.
|
||||
func rewriteTree(path, qual string, paths []string) error {
|
||||
w := fs.Walk(path)
|
||||
for w.Step() {
|
||||
if w.Err() != nil {
|
||||
log.Println("rewrite:", w.Err())
|
||||
continue
|
||||
}
|
||||
s := w.Stat()
|
||||
if s.IsDir() && s.Name() == "testdata" {
|
||||
w.SkipDir()
|
||||
continue
|
||||
}
|
||||
if strings.HasSuffix(w.Path(), ".go") {
|
||||
err := rewriteGoFile(w.Path(), qual, paths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// rewriteGoFile rewrites import statements in the named file
|
||||
// according to the rules for func qualify.
|
||||
func rewriteGoFile(name, qual string, paths []string) error {
|
||||
debugln("rewriteGoFile", name, ",", qual, ",", paths)
|
||||
printerConfig := &printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, name, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var changed bool
|
||||
for _, s := range f.Imports {
|
||||
name, err := strconv.Unquote(s.Path.Value)
|
||||
if err != nil {
|
||||
return err // can't happen
|
||||
}
|
||||
q := qualify(unqualify(name), qual, paths)
|
||||
if q != name {
|
||||
s.Path.Value = strconv.Quote(q)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
if !changed {
|
||||
return nil
|
||||
}
|
||||
var buffer bytes.Buffer
|
||||
if err = printerConfig.Fprint(&buffer, fset, f); err != nil {
|
||||
return err
|
||||
}
|
||||
fset = token.NewFileSet()
|
||||
f, err = parser.ParseFile(fset, name, &buffer, parser.ParseComments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ast.SortImports(fset, f)
|
||||
tpath := name + ".temp"
|
||||
t, err := os.Create(tpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = printerConfig.Fprint(t, fset, f); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = t.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
// This is required before the rename on windows.
|
||||
if err = os.Remove(name); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tpath, name)
|
||||
}
|
||||
|
||||
func defaultSep(experiment bool) string {
|
||||
if experiment {
|
||||
return "/vendor/"
|
||||
}
|
||||
return "/Godeps/_workspace/src/"
|
||||
}
|
||||
|
||||
func relativeVendorTarget(experiment bool) string {
|
||||
full := defaultSep(experiment)
|
||||
if full[0] == '/' {
|
||||
full = full[1:]
|
||||
}
|
||||
return filepath.FromSlash(full)
|
||||
}
|
||||
|
||||
// unqualify returns the part of importPath after the last
|
||||
// occurrence of the signature path elements
|
||||
// (Godeps/_workspace/src) that always precede imported
|
||||
// packages in rewritten import paths.
|
||||
//
|
||||
// For example,
|
||||
// unqualify(C) = C
|
||||
// unqualify(D/Godeps/_workspace/src/C) = C
|
||||
func unqualify(importPath string) string {
|
||||
if i := strings.LastIndex(importPath, sep); i != -1 {
|
||||
importPath = importPath[i+len(sep):]
|
||||
}
|
||||
return importPath
|
||||
}
|
||||
|
||||
// qualify qualifies importPath with its corresponding import
|
||||
// path in the Godeps src copy of package pkg. If importPath
|
||||
// is a directory lexically contained in a path in paths,
|
||||
// it will be qualified with package pkg; otherwise, it will
|
||||
// be returned unchanged.
|
||||
//
|
||||
// For example, given paths {D, T} and pkg C,
|
||||
// importPath returns
|
||||
// C C
|
||||
// fmt fmt
|
||||
// D C/Godeps/_workspace/src/D
|
||||
// D/P C/Godeps/_workspace/src/D/P
|
||||
// T C/Godeps/_workspace/src/T
|
||||
func qualify(importPath, pkg string, paths []string) string {
|
||||
if containsPathPrefix(paths, importPath) {
|
||||
return pkg + sep + importPath
|
||||
}
|
||||
return importPath
|
||||
}
|
612
vendor/k8s.io/kubernetes/third_party/forked/godep/save.go
generated
vendored
Normal file
612
vendor/k8s.io/kubernetes/third_party/forked/godep/save.go
generated
vendored
Normal file
@ -0,0 +1,612 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/kr/fs"
|
||||
)
|
||||
|
||||
var cmdSave = &Command{
|
||||
Name: "save",
|
||||
Args: "[-r] [-t] [packages]",
|
||||
Short: "list and copy dependencies into Godeps",
|
||||
Long: `
|
||||
|
||||
Save writes a list of the named packages and their dependencies along
|
||||
with the exact source control revision of each package, and copies
|
||||
their source code into a subdirectory. Packages inside "." are excluded
|
||||
from the list to be copied.
|
||||
|
||||
The list is written to Godeps/Godeps.json, and source code for all
|
||||
dependencies is copied into either Godeps/_workspace or, if the vendor
|
||||
experiment is turned on, vendor/.
|
||||
|
||||
The dependency list is a JSON document with the following structure:
|
||||
|
||||
type Godeps struct {
|
||||
ImportPath string
|
||||
GoVersion string // Abridged output of 'go version'.
|
||||
Packages []string // Arguments to godep save, if any.
|
||||
Deps []struct {
|
||||
ImportPath string
|
||||
Comment string // Tag or description of commit.
|
||||
Rev string // VCS-specific commit ID.
|
||||
}
|
||||
}
|
||||
|
||||
Any packages already present in the list will be left unchanged.
|
||||
To update a dependency to a newer revision, use 'godep update'.
|
||||
|
||||
If -r is given, import statements will be rewritten to refer directly
|
||||
to the copied source code. This is not compatible with the vendor
|
||||
experiment. Note that this will not rewrite the statements in the
|
||||
files outside the project.
|
||||
|
||||
If -t is given, test files (*_test.go files + testdata directories) are
|
||||
also saved.
|
||||
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
`,
|
||||
Run: runSave,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
var (
|
||||
saveR, saveT bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmdSave.Flag.BoolVar(&saveR, "r", false, "rewrite import paths")
|
||||
cmdSave.Flag.BoolVar(&saveT, "t", false, "save test files")
|
||||
|
||||
}
|
||||
|
||||
func runSave(cmd *Command, args []string) {
|
||||
if VendorExperiment && saveR {
|
||||
log.Println("flag -r is incompatible with the vendoring experiment")
|
||||
cmd.UsageExit()
|
||||
}
|
||||
err := save(args)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
func dotPackage() (*build.Package, error) {
|
||||
dir, err := filepath.Abs(".")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return build.ImportDir(dir, build.FindOnly)
|
||||
}
|
||||
|
||||
func projectPackages(dDir string, a []*Package) []*Package {
|
||||
var projPkgs []*Package
|
||||
dotDir := fmt.Sprintf("%s%c", dDir, filepath.Separator)
|
||||
for _, p := range a {
|
||||
pkgDir := fmt.Sprintf("%s%c", p.Dir, filepath.Separator)
|
||||
if strings.HasPrefix(pkgDir, dotDir) {
|
||||
projPkgs = append(projPkgs, p)
|
||||
}
|
||||
}
|
||||
return projPkgs
|
||||
}
|
||||
|
||||
func save(pkgs []string) error {
|
||||
var err error
|
||||
dp, err := dotPackage()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
debugln("dotPackageImportPath:", dp.ImportPath)
|
||||
debugln("dotPackageDir:", dp.Dir)
|
||||
|
||||
cv, err := goVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
verboseln("Go Version:", cv)
|
||||
|
||||
gold, err := loadDefaultGodepsFile()
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
verboseln("No old Godeps.json found.")
|
||||
gold.GoVersion = cv
|
||||
}
|
||||
|
||||
printVersionWarnings(gold.GoVersion)
|
||||
if len(gold.GoVersion) == 0 {
|
||||
gold.GoVersion = majorGoVersion
|
||||
} else {
|
||||
majorGoVersion, err = trimGoVersion(gold.GoVersion)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to determine go major version from value specified in %s: %s\n", gold.file(), gold.GoVersion)
|
||||
}
|
||||
}
|
||||
|
||||
gnew := &Godeps{
|
||||
ImportPath: dp.ImportPath,
|
||||
GoVersion: gold.GoVersion,
|
||||
}
|
||||
|
||||
switch len(pkgs) {
|
||||
case 0:
|
||||
pkgs = []string{"."}
|
||||
default:
|
||||
gnew.Packages = pkgs
|
||||
}
|
||||
|
||||
verboseln("Finding dependencies for", pkgs)
|
||||
a, err := LoadPackages(pkgs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, p := range a {
|
||||
verboseln("Found package:", p.ImportPath)
|
||||
verboseln("\tDeps:", strings.Join(p.Deps, " "))
|
||||
}
|
||||
ppln(a)
|
||||
|
||||
projA := projectPackages(dp.Dir, a)
|
||||
debugln("Filtered projectPackages")
|
||||
ppln(projA)
|
||||
|
||||
verboseln("Computing new Godeps.json file")
|
||||
err = gnew.fill(a, dp.ImportPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
debugln("New Godeps Filled")
|
||||
ppln(gnew)
|
||||
|
||||
if gnew.Deps == nil {
|
||||
gnew.Deps = make([]Dependency, 0) // produce json [], not null
|
||||
}
|
||||
gdisk := gnew.copy()
|
||||
err = carryVersions(&gold, gnew)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if gold.isOldFile {
|
||||
// If we are migrating from an old format file,
|
||||
// we require that the listed version of every
|
||||
// dependency must be installed in GOPATH, so it's
|
||||
// available to copy.
|
||||
if !eqDeps(gnew.Deps, gdisk.Deps) {
|
||||
return errors.New(strings.TrimSpace(needRestore))
|
||||
}
|
||||
gold = Godeps{}
|
||||
}
|
||||
os.Remove("Godeps") // remove regular file if present; ignore error
|
||||
readme := filepath.Join("Godeps", "Readme")
|
||||
err = writeFile(readme, strings.TrimSpace(Readme)+"\n")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
_, err = gnew.save()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
verboseln("Computing diff between old and new deps")
|
||||
// We use a name starting with "_" so the go tool
|
||||
// ignores this directory when traversing packages
|
||||
// starting at the project's root. For example,
|
||||
// godep go list ./...
|
||||
srcdir := filepath.FromSlash(strings.Trim(sep, "/"))
|
||||
rem := subDeps(gold.Deps, gnew.Deps)
|
||||
ppln(rem)
|
||||
add := subDeps(gnew.Deps, gold.Deps)
|
||||
ppln(add)
|
||||
if len(rem) > 0 {
|
||||
verboseln("Deps to remove:")
|
||||
for _, r := range rem {
|
||||
verboseln("\t", r.ImportPath)
|
||||
}
|
||||
verboseln("Removing unused dependencies")
|
||||
err = removeSrc(srcdir, rem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(add) > 0 {
|
||||
verboseln("Deps to add:")
|
||||
for _, a := range add {
|
||||
verboseln("\t", a.ImportPath)
|
||||
}
|
||||
verboseln("Adding new dependencies")
|
||||
err = copySrc(srcdir, add)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !VendorExperiment {
|
||||
f, _ := filepath.Split(srcdir)
|
||||
writeVCSIgnore(f)
|
||||
}
|
||||
var rewritePaths []string
|
||||
if saveR {
|
||||
for _, dep := range gnew.Deps {
|
||||
rewritePaths = append(rewritePaths, dep.ImportPath)
|
||||
}
|
||||
}
|
||||
verboseln("Rewriting paths (if necessary)")
|
||||
ppln(rewritePaths)
|
||||
return rewrite(projA, dp.ImportPath, rewritePaths)
|
||||
}
|
||||
|
||||
func printVersionWarnings(ov string) {
|
||||
var warning bool
|
||||
cv, err := goVersion()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Trim the old version because we may have saved it w/o trimming it
|
||||
// cv is already trimmed by goVersion()
|
||||
tov, err := trimGoVersion(ov)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if tov != ov {
|
||||
log.Printf("WARNING: Recorded go version (%s) with minor version string found.\n", ov)
|
||||
warning = true
|
||||
}
|
||||
if cv != tov {
|
||||
log.Printf("WARNING: Recorded major go version (%s) and in-use major go version (%s) differ.\n", tov, cv)
|
||||
warning = true
|
||||
}
|
||||
if warning {
|
||||
log.Println("To record current major go version run `godep update -goversion`.")
|
||||
}
|
||||
}
|
||||
|
||||
type revError struct {
|
||||
ImportPath string
|
||||
WantRev string
|
||||
HavePath string
|
||||
HaveRev string
|
||||
}
|
||||
|
||||
func (v *revError) Error() string {
|
||||
return fmt.Sprintf("cannot save %s at revision %s: already have %s at revision %s.\n"+
|
||||
"Run `godep update %s' first.", v.ImportPath, v.WantRev, v.HavePath, v.HaveRev, v.HavePath)
|
||||
}
|
||||
|
||||
// carryVersions copies Rev and Comment from a to b for
|
||||
// each dependency with an identical ImportPath. For any
|
||||
// dependency in b that appears to be from the same repo
|
||||
// as one in a (for example, a parent or child directory),
|
||||
// the Rev must already match - otherwise it is an error.
|
||||
func carryVersions(a, b *Godeps) error {
|
||||
for i := range b.Deps {
|
||||
err := carryVersion(a, &b.Deps[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func carryVersion(a *Godeps, db *Dependency) error {
|
||||
// First see if this exact package is already in the list.
|
||||
for _, da := range a.Deps {
|
||||
if db.ImportPath == da.ImportPath {
|
||||
db.Rev = da.Rev
|
||||
db.Comment = da.Comment
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// No exact match, check for child or sibling package.
|
||||
// We can't handle mismatched versions for packages in
|
||||
// the same repo, so report that as an error.
|
||||
for _, da := range a.Deps {
|
||||
if strings.HasPrefix(db.ImportPath, da.ImportPath+"/") ||
|
||||
strings.HasPrefix(da.ImportPath, db.root+"/") {
|
||||
if da.Rev != db.Rev {
|
||||
return &revError{
|
||||
ImportPath: db.ImportPath,
|
||||
WantRev: db.Rev,
|
||||
HavePath: da.ImportPath,
|
||||
HaveRev: da.Rev,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// No related package in the list, must be a new repo.
|
||||
return nil
|
||||
}
|
||||
|
||||
// subDeps returns a - b, using ImportPath for equality.
|
||||
func subDeps(a, b []Dependency) (diff []Dependency) {
|
||||
Diff:
|
||||
for _, da := range a {
|
||||
for _, db := range b {
|
||||
if da.ImportPath == db.ImportPath {
|
||||
continue Diff
|
||||
}
|
||||
}
|
||||
diff = append(diff, da)
|
||||
}
|
||||
return diff
|
||||
}
|
||||
|
||||
func removeSrc(srcdir string, deps []Dependency) error {
|
||||
for _, dep := range deps {
|
||||
path := filepath.FromSlash(dep.ImportPath)
|
||||
err := os.RemoveAll(filepath.Join(srcdir, path))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copySrc(dir string, deps []Dependency) error {
|
||||
// mapping to see if we visited a parent directory already
|
||||
visited := make(map[string]bool)
|
||||
ok := true
|
||||
for _, dep := range deps {
|
||||
debugln("copySrc for", dep.ImportPath)
|
||||
srcdir := filepath.Join(dep.ws, "src")
|
||||
rel, err := filepath.Rel(srcdir, dep.dir)
|
||||
debugln("srcdir", srcdir)
|
||||
debugln("rel", rel)
|
||||
debugln("err", err)
|
||||
if err != nil { // this should never happen
|
||||
return err
|
||||
}
|
||||
dstpkgroot := filepath.Join(dir, rel)
|
||||
err = os.RemoveAll(dstpkgroot)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
ok = false
|
||||
}
|
||||
|
||||
// copy actual dependency
|
||||
vf := dep.vcs.listFiles(dep.dir)
|
||||
debugln("vf", vf)
|
||||
w := fs.Walk(dep.dir)
|
||||
for w.Step() {
|
||||
err = copyPkgFile(vf, dir, srcdir, w)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
|
||||
// Look for legal files in root
|
||||
// some packages are imports as a sub-package but license info
|
||||
// is at root: exampleorg/common has license file in exampleorg
|
||||
//
|
||||
if dep.ImportPath == dep.root {
|
||||
// we are already at root
|
||||
continue
|
||||
}
|
||||
|
||||
// prevent copying twice This could happen if we have
|
||||
// two subpackages listed someorg/common and
|
||||
// someorg/anotherpack which has their license in
|
||||
// the parent dir of someorg
|
||||
rootdir := filepath.Join(srcdir, filepath.FromSlash(dep.root))
|
||||
if visited[rootdir] {
|
||||
continue
|
||||
}
|
||||
visited[rootdir] = true
|
||||
vf = dep.vcs.listFiles(rootdir)
|
||||
w = fs.Walk(rootdir)
|
||||
for w.Step() {
|
||||
fname := filepath.Base(w.Path())
|
||||
if IsLegalFile(fname) && !strings.Contains(w.Path(), sep) {
|
||||
err = copyPkgFile(vf, dir, srcdir, w)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return errorCopyingSourceCode
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyPkgFile(vf vcsFiles, dstroot, srcroot string, w *fs.Walker) error {
|
||||
if w.Err() != nil {
|
||||
return w.Err()
|
||||
}
|
||||
name := w.Stat().Name()
|
||||
if w.Stat().IsDir() {
|
||||
if name[0] == '.' || name[0] == '_' || (!saveT && name == "testdata") {
|
||||
// Skip directories starting with '.' or '_' or
|
||||
// 'testdata' (last is only skipped if saveT is false)
|
||||
w.SkipDir()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
rel, err := filepath.Rel(srcroot, w.Path())
|
||||
if err != nil { // this should never happen
|
||||
return err
|
||||
}
|
||||
if !saveT && strings.HasSuffix(name, "_test.go") {
|
||||
if verbose {
|
||||
log.Printf("save: skipping test file: %s", w.Path())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !vf.Contains(w.Path()) {
|
||||
if verbose {
|
||||
log.Printf("save: skipping untracked file: %s", w.Path())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return copyFile(filepath.Join(dstroot, rel), w.Path())
|
||||
}
|
||||
|
||||
// copyFile copies a regular file from src to dst.
|
||||
// dst is opened with os.Create.
|
||||
// If the file name ends with .go,
|
||||
// copyFile strips canonical import path annotations.
|
||||
// These are comments of the form:
|
||||
// package foo // import "bar/foo"
|
||||
// package foo /* import "bar/foo" */
|
||||
func copyFile(dst, src string) error {
|
||||
err := os.MkdirAll(filepath.Dir(dst), 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
linkDst, err := os.Readlink(src)
|
||||
if err == nil {
|
||||
return os.Symlink(linkDst, dst)
|
||||
}
|
||||
|
||||
si, err := stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
w, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Chmod(dst, si.Mode()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.HasSuffix(dst, ".go") {
|
||||
debugln("Copy Without Import Comment", w, r)
|
||||
err = copyWithoutImportComment(w, r)
|
||||
} else {
|
||||
debugln("Copy (plain)", w, r)
|
||||
_, err = io.Copy(w, r)
|
||||
}
|
||||
err1 := w.Close()
|
||||
if err == nil {
|
||||
err = err1
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func copyWithoutImportComment(w io.Writer, r io.Reader) error {
|
||||
b := bufio.NewReader(r)
|
||||
for {
|
||||
l, err := b.ReadBytes('\n')
|
||||
eof := err == io.EOF
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
// If we have data then write it out...
|
||||
if len(l) > 0 {
|
||||
// Strip off \n if it exists because stripImportComment
|
||||
_, err := w.Write(append(stripImportComment(bytes.TrimRight(l, "\n")), '\n'))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if eof {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
importAnnotation = `import\s+(?:"[^"]*"|` + "`[^`]*`" + `)`
|
||||
importComment = `(?://\s*` + importAnnotation + `\s*$|/\*\s*` + importAnnotation + `\s*\*/)`
|
||||
)
|
||||
|
||||
var (
|
||||
importCommentRE = regexp.MustCompile(`^\s*(package\s+\w+)\s+` + importComment + `(.*)`)
|
||||
pkgPrefix = []byte("package ")
|
||||
)
|
||||
|
||||
// stripImportComment returns line with its import comment removed.
|
||||
// If s is not a package statement containing an import comment,
|
||||
// it is returned unaltered.
|
||||
// FIXME: expects lines w/o a \n at the end
|
||||
// See also http://golang.org/s/go14customimport.
|
||||
func stripImportComment(line []byte) []byte {
|
||||
if !bytes.HasPrefix(line, pkgPrefix) {
|
||||
// Fast path; this will skip all but one line in the file.
|
||||
// This assumes there is no whitespace before the keyword.
|
||||
return line
|
||||
}
|
||||
if m := importCommentRE.FindSubmatch(line); m != nil {
|
||||
return append(m[1], m[2]...)
|
||||
}
|
||||
return line
|
||||
}
|
||||
|
||||
// Func writeVCSIgnore writes "ignore" files inside dir for known VCSs,
|
||||
// so that dir/pkg and dir/bin don't accidentally get committed.
|
||||
// It logs any errors it encounters.
|
||||
func writeVCSIgnore(dir string) {
|
||||
// Currently git is the only VCS for which we know how to do this.
|
||||
// Mercurial and Bazaar have similar mechanisms, but they apparently
|
||||
// require writing files outside of dir.
|
||||
const ignore = "/pkg\n/bin\n"
|
||||
name := filepath.Join(dir, ".gitignore")
|
||||
err := writeFile(name, ignore)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
// writeFile is like ioutil.WriteFile but it creates
|
||||
// intermediate directories with os.MkdirAll.
|
||||
func writeFile(name, body string) error {
|
||||
err := os.MkdirAll(filepath.Dir(name), 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(name, []byte(body), 0666)
|
||||
}
|
||||
|
||||
const (
|
||||
// Readme contains the README text.
|
||||
Readme = `
|
||||
This directory tree is generated automatically by godep.
|
||||
|
||||
Please do not edit.
|
||||
|
||||
See https://github.com/tools/godep for more information.
|
||||
`
|
||||
needRestore = `
|
||||
mismatched versions while migrating
|
||||
|
||||
It looks like you are switching from the old Godeps format
|
||||
(from flag -copy=false). The old format is just a file; it
|
||||
doesn't contain source code. For this migration, godep needs
|
||||
the appropriate version of each dependency to be installed in
|
||||
GOPATH, so that the source code is available to copy.
|
||||
|
||||
To fix this, run 'godep restore'.
|
||||
`
|
||||
)
|
292
vendor/k8s.io/kubernetes/third_party/forked/godep/update.go
generated
vendored
Normal file
292
vendor/k8s.io/kubernetes/third_party/forked/godep/update.go
generated
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var cmdUpdate = &Command{
|
||||
Name: "update",
|
||||
Args: "[-goversion] [packages]",
|
||||
Short: "update selected packages or the go version",
|
||||
Long: `
|
||||
Update changes the named dependency packages to use the
|
||||
revision of each currently installed in GOPATH. New code will
|
||||
be copied into the Godeps workspace or vendor folder and the
|
||||
new revision will be written to the manifest.
|
||||
|
||||
If -goversion is specified, update the recorded go version.
|
||||
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
`,
|
||||
Run: runUpdate,
|
||||
OnlyInGOPATH: true,
|
||||
}
|
||||
|
||||
var (
|
||||
updateGoVer bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmdUpdate.Flag.BoolVar(&saveT, "t", false, "save test files during update")
|
||||
cmdUpdate.Flag.BoolVar(&updateGoVer, "goversion", false, "update the recorded go version")
|
||||
}
|
||||
|
||||
func runUpdate(cmd *Command, args []string) {
|
||||
if updateGoVer {
|
||||
err := updateGoVersion()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
if len(args) > 0 {
|
||||
err := update(args)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateGoVersion() error {
|
||||
gold, err := loadDefaultGodepsFile()
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
cv, err := goVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gv := gold.GoVersion
|
||||
gold.GoVersion = cv
|
||||
_, err = gold.save()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if gv != cv {
|
||||
log.Println("Updated major go version to", cv)
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func update(args []string) error {
|
||||
if len(args) == 0 {
|
||||
args = []string{"."}
|
||||
}
|
||||
g, err := loadDefaultGodepsFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, arg := range args {
|
||||
arg := path.Clean(arg)
|
||||
any := markMatches(arg, g.Deps)
|
||||
if !any {
|
||||
log.Println("not in manifest:", arg)
|
||||
}
|
||||
}
|
||||
deps, rdeps, err := LoadVCSAndUpdate(g.Deps)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(deps) == 0 {
|
||||
return errorNoPackagesUpdatable
|
||||
}
|
||||
g.addOrUpdateDeps(deps)
|
||||
g.removeDeps(rdeps)
|
||||
if _, err = g.save(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
srcdir := relativeVendorTarget(VendorExperiment)
|
||||
if err := removeSrc(filepath.FromSlash(strings.Trim(sep, "/")), rdeps); err != nil {
|
||||
return err
|
||||
}
|
||||
copySrc(srcdir, deps)
|
||||
|
||||
ok, err := needRewrite(g.Packages)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var rewritePaths []string
|
||||
if ok {
|
||||
for _, dep := range g.Deps {
|
||||
rewritePaths = append(rewritePaths, dep.ImportPath)
|
||||
}
|
||||
}
|
||||
return rewrite(nil, g.ImportPath, rewritePaths)
|
||||
}
|
||||
|
||||
func needRewrite(importPaths []string) (bool, error) {
|
||||
if len(importPaths) == 0 {
|
||||
importPaths = []string{"."}
|
||||
}
|
||||
a, err := LoadPackages(importPaths...)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, p := range a {
|
||||
for _, name := range p.allGoFiles() {
|
||||
path := filepath.Join(p.Dir, name)
|
||||
hasSep, err := hasRewrittenImportStatement(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if hasSep {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func hasRewrittenImportStatement(path string) (bool, error) {
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, path, nil, 0)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, s := range f.Imports {
|
||||
name, _ := strconv.Unquote(s.Path.Value)
|
||||
if strings.Contains(name, sep) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// markMatches marks each entry in deps with an import path that
|
||||
// matches pat. It returns whether any matches occurred.
|
||||
func markMatches(pat string, deps []Dependency) (matched bool) {
|
||||
f := matchPattern(pat)
|
||||
for i, dep := range deps {
|
||||
if f(dep.ImportPath) {
|
||||
deps[i].matched = true
|
||||
matched = true
|
||||
}
|
||||
}
|
||||
return matched
|
||||
}
|
||||
|
||||
func fillDeps(deps []Dependency) ([]Dependency, error) {
|
||||
for i := range deps {
|
||||
if deps[i].pkg != nil {
|
||||
continue
|
||||
}
|
||||
ps, err := LoadPackages(deps[i].ImportPath)
|
||||
if err != nil {
|
||||
if _, ok := err.(errPackageNotFound); ok {
|
||||
deps[i].missing = true
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if len(ps) > 1 {
|
||||
panic("More than one package found for " + deps[i].ImportPath)
|
||||
}
|
||||
p := ps[0]
|
||||
deps[i].pkg = p
|
||||
deps[i].dir = p.Dir
|
||||
deps[i].ws = p.Root
|
||||
|
||||
vcs, reporoot, err := VCSFromDir(p.Dir, filepath.Join(p.Root, "src"))
|
||||
if err != nil {
|
||||
return nil, errorLoadingDeps
|
||||
}
|
||||
deps[i].root = filepath.ToSlash(reporoot)
|
||||
deps[i].vcs = vcs
|
||||
}
|
||||
|
||||
return deps, nil
|
||||
}
|
||||
|
||||
// LoadVCSAndUpdate loads and updates a set of dependencies.
|
||||
func LoadVCSAndUpdate(deps []Dependency) ([]Dependency, []Dependency, error) {
|
||||
var err1 error
|
||||
|
||||
deps, err := fillDeps(deps)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
repoMask := make(map[string]bool)
|
||||
for i := range deps {
|
||||
if !deps[i].matched {
|
||||
repoMask[deps[i].root] = true
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if we need any new packages because of new transitive imports
|
||||
for _, dep := range deps {
|
||||
if !dep.matched || dep.missing {
|
||||
continue
|
||||
}
|
||||
for _, dp := range dep.pkg.Dependencies {
|
||||
if dp.Goroot {
|
||||
continue
|
||||
}
|
||||
var have bool
|
||||
for _, d := range deps {
|
||||
if d.ImportPath == dp.ImportPath {
|
||||
have = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !have {
|
||||
deps = append(deps, Dependency{ImportPath: dp.ImportPath, matched: true})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deps, err = fillDeps(deps)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var toUpdate, toRemove []Dependency
|
||||
for _, d := range deps {
|
||||
if !d.matched || repoMask[d.root] {
|
||||
continue
|
||||
}
|
||||
if d.missing {
|
||||
toRemove = append(toRemove, d)
|
||||
continue
|
||||
}
|
||||
toUpdate = append(toUpdate, d)
|
||||
}
|
||||
|
||||
debugln("toUpdate")
|
||||
ppln(toUpdate)
|
||||
|
||||
var toCopy []Dependency
|
||||
for _, d := range toUpdate {
|
||||
id, err := d.vcs.identify(d.dir)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
err1 = errorLoadingDeps
|
||||
continue
|
||||
}
|
||||
if d.vcs.isDirty(d.dir, id) {
|
||||
log.Println("dirty working tree (please commit changes):", d.dir)
|
||||
}
|
||||
d.Rev = id
|
||||
d.Comment = d.vcs.describe(d.dir, id)
|
||||
toCopy = append(toCopy, d)
|
||||
}
|
||||
debugln("toCopy")
|
||||
ppln(toCopy)
|
||||
|
||||
if err1 != nil {
|
||||
return nil, nil, err1
|
||||
}
|
||||
return toCopy, toRemove, nil
|
||||
}
|
36
vendor/k8s.io/kubernetes/third_party/forked/godep/util.go
generated
vendored
Normal file
36
vendor/k8s.io/kubernetes/third_party/forked/godep/util.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// driveLetterToUpper converts Windows path's drive letters to uppercase. This
|
||||
// is needed when comparing 2 paths with different drive letter case.
|
||||
func driveLetterToUpper(path string) string {
|
||||
if runtime.GOOS != "windows" || path == "" {
|
||||
return path
|
||||
}
|
||||
|
||||
p := path
|
||||
|
||||
// If path's drive letter is lowercase, change it to uppercase.
|
||||
if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' {
|
||||
p = string(p[0]+'A'-'a') + p[1:]
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// clean the path and ensure that a drive letter is upper case (if it exists).
|
||||
func cleanPath(path string) string {
|
||||
return driveLetterToUpper(filepath.Clean(path))
|
||||
}
|
||||
|
||||
// deal with case insensitive filesystems and other weirdness
|
||||
func pathEqual(a, b string) bool {
|
||||
a = cleanPath(a)
|
||||
b = cleanPath(b)
|
||||
return strings.EqualFold(a, b)
|
||||
}
|
293
vendor/k8s.io/kubernetes/third_party/forked/godep/vcs.go
generated
vendored
Normal file
293
vendor/k8s.io/kubernetes/third_party/forked/godep/vcs.go
generated
vendored
Normal file
@ -0,0 +1,293 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/vcs"
|
||||
)
|
||||
|
||||
// VCS represents a version control system.
|
||||
type VCS struct {
|
||||
vcs *vcs.Cmd
|
||||
|
||||
IdentifyCmd string
|
||||
DescribeCmd string
|
||||
DiffCmd string
|
||||
ListCmd string
|
||||
RootCmd string
|
||||
|
||||
// run in sandbox repos
|
||||
ExistsCmd string
|
||||
}
|
||||
|
||||
var vcsBzr = &VCS{
|
||||
vcs: vcs.ByCmd("bzr"),
|
||||
|
||||
IdentifyCmd: "version-info --custom --template {revision_id}",
|
||||
DescribeCmd: "revno", // TODO(kr): find tag names if possible
|
||||
DiffCmd: "diff -r {rev}",
|
||||
ListCmd: "ls --from-root -R",
|
||||
RootCmd: "root",
|
||||
}
|
||||
|
||||
var vcsGit = &VCS{
|
||||
vcs: vcs.ByCmd("git"),
|
||||
|
||||
IdentifyCmd: "rev-parse HEAD",
|
||||
DescribeCmd: "describe --tags --abbrev=14",
|
||||
DiffCmd: "diff {rev}",
|
||||
ListCmd: "ls-files --full-name",
|
||||
RootCmd: "rev-parse --show-cdup",
|
||||
|
||||
ExistsCmd: "cat-file -e {rev}",
|
||||
}
|
||||
|
||||
var vcsHg = &VCS{
|
||||
vcs: vcs.ByCmd("hg"),
|
||||
|
||||
IdentifyCmd: "parents --template {node}",
|
||||
DescribeCmd: "log -r . --template {latesttag}-{latesttagdistance}",
|
||||
DiffCmd: "diff -r {rev}",
|
||||
ListCmd: "status --all --no-status",
|
||||
RootCmd: "root",
|
||||
|
||||
ExistsCmd: "cat -r {rev} .",
|
||||
}
|
||||
|
||||
var cmd = map[*vcs.Cmd]*VCS{
|
||||
vcsBzr.vcs: vcsBzr,
|
||||
vcsGit.vcs: vcsGit,
|
||||
vcsHg.vcs: vcsHg,
|
||||
}
|
||||
|
||||
// VCSFromDir returns a VCS value from a directory.
|
||||
func VCSFromDir(dir, srcRoot string) (*VCS, string, error) {
|
||||
vcscmd, reporoot, err := vcs.FromDir(dir, srcRoot)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("error while inspecting %q: %v", dir, err)
|
||||
}
|
||||
vcsext := cmd[vcscmd]
|
||||
if vcsext == nil {
|
||||
return nil, "", fmt.Errorf("%s is unsupported: %s", vcscmd.Name, dir)
|
||||
}
|
||||
return vcsext, reporoot, nil
|
||||
}
|
||||
|
||||
func (v *VCS) identify(dir string) (string, error) {
|
||||
out, err := v.runOutput(dir, v.IdentifyCmd)
|
||||
return string(bytes.TrimSpace(out)), err
|
||||
}
|
||||
|
||||
func absRoot(dir, out string) string {
|
||||
if filepath.IsAbs(out) {
|
||||
return filepath.Clean(out)
|
||||
}
|
||||
return filepath.Join(dir, out)
|
||||
}
|
||||
|
||||
func (v *VCS) root(dir string) (string, error) {
|
||||
out, err := v.runOutput(dir, v.RootCmd)
|
||||
return absRoot(dir, string(bytes.TrimSpace(out))), err
|
||||
}
|
||||
|
||||
func (v *VCS) describe(dir, rev string) string {
|
||||
out, err := v.runOutputVerboseOnly(dir, v.DescribeCmd, "rev", rev)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(bytes.TrimSpace(out))
|
||||
}
|
||||
|
||||
func (v *VCS) isDirty(dir, rev string) bool {
|
||||
out, err := v.runOutput(dir, v.DiffCmd, "rev", rev)
|
||||
return err != nil || len(out) != 0
|
||||
}
|
||||
|
||||
type vcsFiles map[string]bool
|
||||
|
||||
func (vf vcsFiles) Contains(path string) bool {
|
||||
// Fast path, we have the path
|
||||
if vf[path] {
|
||||
return true
|
||||
}
|
||||
|
||||
// Slow path for case insensitive filesystems
|
||||
// See #310
|
||||
for f := range vf {
|
||||
if pathEqual(f, path) {
|
||||
return true
|
||||
}
|
||||
// git's root command (maybe other vcs as well) resolve symlinks, so try that too
|
||||
// FIXME: rev-parse --show-cdup + extra logic will fix this for git but also need to validate the other vcs commands. This is maybe temporary.
|
||||
p, err := filepath.EvalSymlinks(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if pathEqual(f, p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// No matches by either method
|
||||
return false
|
||||
}
|
||||
|
||||
// listFiles tracked by the VCS in the repo that contains dir, converted to absolute path.
|
||||
func (v *VCS) listFiles(dir string) vcsFiles {
|
||||
root, err := v.root(dir)
|
||||
debugln("vcs dir", dir)
|
||||
debugln("vcs root", root)
|
||||
ppln(v)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
out, err := v.runOutput(dir, v.ListCmd)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
files := make(vcsFiles)
|
||||
for _, file := range bytes.Split(out, []byte{'\n'}) {
|
||||
if len(file) > 0 {
|
||||
path, err := filepath.Abs(filepath.Join(root, string(file)))
|
||||
if err != nil {
|
||||
panic(err) // this should not happen
|
||||
}
|
||||
|
||||
if pathEqual(filepath.Dir(path), dir) {
|
||||
files[path] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
func (v *VCS) exists(dir, rev string) bool {
|
||||
err := v.runVerboseOnly(dir, v.ExistsCmd, "rev", rev)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// RevSync checks out the revision given by rev in dir.
|
||||
// The dir must exist and rev must be a valid revision.
|
||||
func (v *VCS) RevSync(dir, rev string) error {
|
||||
return v.run(dir, v.vcs.TagSyncCmd, "tag", rev)
|
||||
}
|
||||
|
||||
// run runs the command line cmd in the given directory.
|
||||
// keyval is a list of key, value pairs. run expands
|
||||
// instances of {key} in cmd into value, but only after
|
||||
// splitting cmd into individual arguments.
|
||||
// If an error occurs, run prints the command line and the
|
||||
// command's combined stdout+stderr to standard error.
|
||||
// Otherwise run discards the command's output.
|
||||
func (v *VCS) run(dir string, cmdline string, kv ...string) error {
|
||||
_, err := v.run1(dir, cmdline, kv, true)
|
||||
return err
|
||||
}
|
||||
|
||||
// runVerboseOnly is like run but only generates error output to standard error in verbose mode.
|
||||
func (v *VCS) runVerboseOnly(dir string, cmdline string, kv ...string) error {
|
||||
_, err := v.run1(dir, cmdline, kv, false)
|
||||
return err
|
||||
}
|
||||
|
||||
// runOutput is like run but returns the output of the command.
|
||||
func (v *VCS) runOutput(dir string, cmdline string, kv ...string) ([]byte, error) {
|
||||
return v.run1(dir, cmdline, kv, true)
|
||||
}
|
||||
|
||||
// runOutputVerboseOnly is like runOutput but only generates error output to standard error in verbose mode.
|
||||
func (v *VCS) runOutputVerboseOnly(dir string, cmdline string, kv ...string) ([]byte, error) {
|
||||
return v.run1(dir, cmdline, kv, false)
|
||||
}
|
||||
|
||||
// run1 is the generalized implementation of run and runOutput.
|
||||
func (v *VCS) run1(dir string, cmdline string, kv []string, verbose bool) ([]byte, error) {
|
||||
m := make(map[string]string)
|
||||
for i := 0; i < len(kv); i += 2 {
|
||||
m[kv[i]] = kv[i+1]
|
||||
}
|
||||
args := strings.Fields(cmdline)
|
||||
for i, arg := range args {
|
||||
args[i] = expand(m, arg)
|
||||
}
|
||||
|
||||
_, err := exec.LookPath(v.vcs.Cmd)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "godep: missing %s command.\n", v.vcs.Name)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cmd := exec.Command(v.vcs.Cmd, args...)
|
||||
cmd.Dir = dir
|
||||
var buf bytes.Buffer
|
||||
cmd.Stdout = &buf
|
||||
cmd.Stderr = &buf
|
||||
err = cmd.Run()
|
||||
out := buf.Bytes()
|
||||
if err != nil {
|
||||
if verbose {
|
||||
fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.vcs.Cmd, strings.Join(args, " "))
|
||||
os.Stderr.Write(out)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func expand(m map[string]string, s string) string {
|
||||
for k, v := range m {
|
||||
s = strings.Replace(s, "{"+k+"}", v, -1)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func gitDetached(r string) (bool, error) {
|
||||
o, err := vcsGit.runOutput(r, "status")
|
||||
if err != nil {
|
||||
return false, errors.New("unable to determine git status " + err.Error())
|
||||
}
|
||||
return bytes.Contains(o, []byte("HEAD detached at")), nil
|
||||
}
|
||||
|
||||
func gitDefaultBranch(r string) (string, error) {
|
||||
o, err := vcsGit.runOutput(r, "remote show origin")
|
||||
if err != nil {
|
||||
return "", errors.New("Running git remote show origin errored with: " + err.Error())
|
||||
}
|
||||
return gitDetermineDefaultBranch(r, string(o))
|
||||
}
|
||||
|
||||
func gitDetermineDefaultBranch(r, o string) (string, error) {
|
||||
e := "Unable to determine HEAD branch: "
|
||||
hb := "HEAD branch:"
|
||||
lbcfgp := "Local branch configured for 'git pull':"
|
||||
s := strings.Index(o, hb)
|
||||
if s < 0 {
|
||||
b := strings.Index(o, lbcfgp)
|
||||
if b < 0 {
|
||||
return "", errors.New(e + "Remote HEAD is ambiguous. Before godep can pull new commits you will need to:" + `
|
||||
cd ` + r + `
|
||||
git checkout <a HEAD branch>
|
||||
Here is what was reported:
|
||||
` + o)
|
||||
}
|
||||
s = b + len(lbcfgp)
|
||||
} else {
|
||||
s += len(hb)
|
||||
}
|
||||
f := strings.Fields(o[s:])
|
||||
if len(f) < 3 {
|
||||
return "", errors.New(e + "git output too short")
|
||||
}
|
||||
return f[0], nil
|
||||
}
|
||||
|
||||
func gitCheckout(r, b string) error {
|
||||
return vcsGit.run(r, "checkout "+b)
|
||||
}
|
63
vendor/k8s.io/kubernetes/third_party/forked/godep/version.go
generated
vendored
Normal file
63
vendor/k8s.io/kubernetes/third_party/forked/godep/version.go
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const version = "80-k8s-r1"
|
||||
|
||||
var cmdVersion = &Command{
|
||||
Name: "version",
|
||||
Short: "show version info",
|
||||
Long: `
|
||||
|
||||
Displays the version of godep as well as the target OS, architecture and go runtime version.
|
||||
`,
|
||||
Run: runVersion,
|
||||
}
|
||||
|
||||
func versionString() string {
|
||||
return fmt.Sprintf("godep v%s (%s/%s/%s)", version, runtime.GOOS, runtime.GOARCH, runtime.Version())
|
||||
}
|
||||
|
||||
func runVersion(cmd *Command, args []string) {
|
||||
fmt.Printf("%s\n", versionString())
|
||||
}
|
||||
|
||||
func GoVersionFields(c rune) bool {
|
||||
return c == 'g' || c == 'o' || c == '.'
|
||||
}
|
||||
|
||||
// isSameOrNewer go version (goA.B)
|
||||
// go1.6 >= go1.6 == true
|
||||
// go1.5 >= go1.6 == false
|
||||
func isSameOrNewer(base, check string) bool {
|
||||
if base == check {
|
||||
return true
|
||||
}
|
||||
if strings.HasPrefix(check, "devel-") {
|
||||
return true
|
||||
}
|
||||
bp := strings.FieldsFunc(base, GoVersionFields)
|
||||
cp := strings.FieldsFunc(check, GoVersionFields)
|
||||
if len(bp) < 2 || len(cp) < 2 {
|
||||
log.Fatalf("Error comparing %s to %s\n", base, check)
|
||||
}
|
||||
if bp[0] == cp[0] { // We only have go version 1 right now
|
||||
bm, err := strconv.Atoi(bp[1])
|
||||
// These errors are unlikely and there is nothing nice to do here anyway
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cm, err := strconv.Atoi(cp[1])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return cm >= bm
|
||||
}
|
||||
return false
|
||||
}
|
3
vendor/k8s.io/kubernetes/third_party/forked/golang/expansion/expand_test.go
generated
vendored
3
vendor/k8s.io/kubernetes/third_party/forked/golang/expansion/expand_test.go
generated
vendored
@ -2,7 +2,8 @@ package expansion
|
||||
|
||||
import (
|
||||
"testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
func TestMapReference(t *testing.T) {
|
||||
|
56
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/BUILD
generated
vendored
56
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/BUILD
generated
vendored
@ -1,56 +0,0 @@
|
||||
licenses(["notice"])
|
||||
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"api.go",
|
||||
"assignments.go",
|
||||
"builtins.go",
|
||||
"call.go",
|
||||
"check.go",
|
||||
"conversions.go",
|
||||
"decl.go",
|
||||
"errors.go",
|
||||
"eval.go",
|
||||
"expr.go",
|
||||
"exprstring.go",
|
||||
"initorder.go",
|
||||
"labels.go",
|
||||
"lookup.go",
|
||||
"methodset.go",
|
||||
"object.go",
|
||||
"objset.go",
|
||||
"operand.go",
|
||||
"ordering.go",
|
||||
"package.go",
|
||||
"predicates.go",
|
||||
"resolver.go",
|
||||
"return.go",
|
||||
"scope.go",
|
||||
"selection.go",
|
||||
"sizes.go",
|
||||
"stmt.go",
|
||||
"type.go",
|
||||
"typestring.go",
|
||||
"typexpr.go",
|
||||
"universe.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/third_party/forked/golang/go/types",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
7
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/README
generated
vendored
7
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/README
generated
vendored
@ -1,7 +0,0 @@
|
||||
This is go/types forked from go@236abdb46b (just after 1.10) and cherry-picked
|
||||
1006f703ffc, which fixes https://github.com/golang/go/issues/23712.
|
||||
|
||||
It can be removed when all builders are >= go1.11.
|
||||
|
||||
Do *not* update this to newer code if https://github.com/golang/go/issues/23914
|
||||
has not been fixed!
|
376
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/api.go
generated
vendored
376
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/api.go
generated
vendored
@ -1,376 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package types declares the data types and implements
|
||||
// the algorithms for type-checking of Go packages. Use
|
||||
// Config.Check to invoke the type checker for a package.
|
||||
// Alternatively, create a new type checker with NewChecker
|
||||
// and invoke it incrementally by calling Checker.Files.
|
||||
//
|
||||
// Type-checking consists of several interdependent phases:
|
||||
//
|
||||
// Name resolution maps each identifier (ast.Ident) in the program to the
|
||||
// language object (Object) it denotes.
|
||||
// Use Info.{Defs,Uses,Implicits} for the results of name resolution.
|
||||
//
|
||||
// Constant folding computes the exact constant value (constant.Value)
|
||||
// for every expression (ast.Expr) that is a compile-time constant.
|
||||
// Use Info.Types[expr].Value for the results of constant folding.
|
||||
//
|
||||
// Type inference computes the type (Type) of every expression (ast.Expr)
|
||||
// and checks for compliance with the language specification.
|
||||
// Use Info.Types[expr].Type for the results of type inference.
|
||||
//
|
||||
// For a tutorial, see https://golang.org/s/types-tutorial.
|
||||
//
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// An Error describes a type-checking error; it implements the error interface.
|
||||
// A "soft" error is an error that still permits a valid interpretation of a
|
||||
// package (such as "unused variable"); "hard" errors may lead to unpredictable
|
||||
// behavior if ignored.
|
||||
type Error struct {
|
||||
Fset *token.FileSet // file set for interpretation of Pos
|
||||
Pos token.Pos // error position
|
||||
Msg string // error message
|
||||
Soft bool // if set, error is "soft"
|
||||
}
|
||||
|
||||
// Error returns an error string formatted as follows:
|
||||
// filename:line:column: message
|
||||
func (err Error) Error() string {
|
||||
return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg)
|
||||
}
|
||||
|
||||
// An Importer resolves import paths to Packages.
|
||||
//
|
||||
// CAUTION: This interface does not support the import of locally
|
||||
// vendored packages. See https://golang.org/s/go15vendor.
|
||||
// If possible, external implementations should implement ImporterFrom.
|
||||
type Importer interface {
|
||||
// Import returns the imported package for the given import path.
|
||||
// The semantics is like for ImporterFrom.ImportFrom except that
|
||||
// dir and mode are ignored (since they are not present).
|
||||
Import(path string) (*Package, error)
|
||||
}
|
||||
|
||||
// ImportMode is reserved for future use.
|
||||
type ImportMode int
|
||||
|
||||
// An ImporterFrom resolves import paths to packages; it
|
||||
// supports vendoring per https://golang.org/s/go15vendor.
|
||||
// Use go/importer to obtain an ImporterFrom implementation.
|
||||
type ImporterFrom interface {
|
||||
// Importer is present for backward-compatibility. Calling
|
||||
// Import(path) is the same as calling ImportFrom(path, "", 0);
|
||||
// i.e., locally vendored packages may not be found.
|
||||
// The types package does not call Import if an ImporterFrom
|
||||
// is present.
|
||||
Importer
|
||||
|
||||
// ImportFrom returns the imported package for the given import
|
||||
// path when imported by a package file located in dir.
|
||||
// If the import failed, besides returning an error, ImportFrom
|
||||
// is encouraged to cache and return a package anyway, if one
|
||||
// was created. This will reduce package inconsistencies and
|
||||
// follow-on type checker errors due to the missing package.
|
||||
// The mode value must be 0; it is reserved for future use.
|
||||
// Two calls to ImportFrom with the same path and dir must
|
||||
// return the same package.
|
||||
ImportFrom(path, dir string, mode ImportMode) (*Package, error)
|
||||
}
|
||||
|
||||
// A Config specifies the configuration for type checking.
|
||||
// The zero value for Config is a ready-to-use default configuration.
|
||||
type Config struct {
|
||||
// If IgnoreFuncBodies is set, function bodies are not
|
||||
// type-checked.
|
||||
IgnoreFuncBodies bool
|
||||
|
||||
// If FakeImportC is set, `import "C"` (for packages requiring Cgo)
|
||||
// declares an empty "C" package and errors are omitted for qualified
|
||||
// identifiers referring to package C (which won't find an object).
|
||||
// This feature is intended for the standard library cmd/api tool.
|
||||
//
|
||||
// Caution: Effects may be unpredictable due to follow-on errors.
|
||||
// Do not use casually!
|
||||
FakeImportC bool
|
||||
|
||||
// If Error != nil, it is called with each error found
|
||||
// during type checking; err has dynamic type Error.
|
||||
// Secondary errors (for instance, to enumerate all types
|
||||
// involved in an invalid recursive type declaration) have
|
||||
// error strings that start with a '\t' character.
|
||||
// If Error == nil, type-checking stops with the first
|
||||
// error found.
|
||||
Error func(err error)
|
||||
|
||||
// An importer is used to import packages referred to from
|
||||
// import declarations.
|
||||
// If the installed importer implements ImporterFrom, the type
|
||||
// checker calls ImportFrom instead of Import.
|
||||
// The type checker reports an error if an importer is needed
|
||||
// but none was installed.
|
||||
Importer Importer
|
||||
|
||||
// If Sizes != nil, it provides the sizing functions for package unsafe.
|
||||
// Otherwise SizesFor("gc", "amd64") is used instead.
|
||||
Sizes Sizes
|
||||
|
||||
// If DisableUnusedImportCheck is set, packages are not checked
|
||||
// for unused imports.
|
||||
DisableUnusedImportCheck bool
|
||||
}
|
||||
|
||||
// Info holds result type information for a type-checked package.
|
||||
// Only the information for which a map is provided is collected.
|
||||
// If the package has type errors, the collected information may
|
||||
// be incomplete.
|
||||
type Info struct {
|
||||
// Types maps expressions to their types, and for constant
|
||||
// expressions, also their values. Invalid expressions are
|
||||
// omitted.
|
||||
//
|
||||
// For (possibly parenthesized) identifiers denoting built-in
|
||||
// functions, the recorded signatures are call-site specific:
|
||||
// if the call result is not a constant, the recorded type is
|
||||
// an argument-specific signature. Otherwise, the recorded type
|
||||
// is invalid.
|
||||
//
|
||||
// The Types map does not record the type of every identifier,
|
||||
// only those that appear where an arbitrary expression is
|
||||
// permitted. For instance, the identifier f in a selector
|
||||
// expression x.f is found only in the Selections map, the
|
||||
// identifier z in a variable declaration 'var z int' is found
|
||||
// only in the Defs map, and identifiers denoting packages in
|
||||
// qualified identifiers are collected in the Uses map.
|
||||
Types map[ast.Expr]TypeAndValue
|
||||
|
||||
// Defs maps identifiers to the objects they define (including
|
||||
// package names, dots "." of dot-imports, and blank "_" identifiers).
|
||||
// For identifiers that do not denote objects (e.g., the package name
|
||||
// in package clauses, or symbolic variables t in t := x.(type) of
|
||||
// type switch headers), the corresponding objects are nil.
|
||||
//
|
||||
// For an anonymous field, Defs returns the field *Var it defines.
|
||||
//
|
||||
// Invariant: Defs[id] == nil || Defs[id].Pos() == id.Pos()
|
||||
Defs map[*ast.Ident]Object
|
||||
|
||||
// Uses maps identifiers to the objects they denote.
|
||||
//
|
||||
// For an anonymous field, Uses returns the *TypeName it denotes.
|
||||
//
|
||||
// Invariant: Uses[id].Pos() != id.Pos()
|
||||
Uses map[*ast.Ident]Object
|
||||
|
||||
// Implicits maps nodes to their implicitly declared objects, if any.
|
||||
// The following node and object types may appear:
|
||||
//
|
||||
// node declared object
|
||||
//
|
||||
// *ast.ImportSpec *PkgName for imports without renames
|
||||
// *ast.CaseClause type-specific *Var for each type switch case clause (incl. default)
|
||||
// *ast.Field anonymous parameter *Var
|
||||
//
|
||||
Implicits map[ast.Node]Object
|
||||
|
||||
// Selections maps selector expressions (excluding qualified identifiers)
|
||||
// to their corresponding selections.
|
||||
Selections map[*ast.SelectorExpr]*Selection
|
||||
|
||||
// Scopes maps ast.Nodes to the scopes they define. Package scopes are not
|
||||
// associated with a specific node but with all files belonging to a package.
|
||||
// Thus, the package scope can be found in the type-checked Package object.
|
||||
// Scopes nest, with the Universe scope being the outermost scope, enclosing
|
||||
// the package scope, which contains (one or more) files scopes, which enclose
|
||||
// function scopes which in turn enclose statement and function literal scopes.
|
||||
// Note that even though package-level functions are declared in the package
|
||||
// scope, the function scopes are embedded in the file scope of the file
|
||||
// containing the function declaration.
|
||||
//
|
||||
// The following node types may appear in Scopes:
|
||||
//
|
||||
// *ast.File
|
||||
// *ast.FuncType
|
||||
// *ast.BlockStmt
|
||||
// *ast.IfStmt
|
||||
// *ast.SwitchStmt
|
||||
// *ast.TypeSwitchStmt
|
||||
// *ast.CaseClause
|
||||
// *ast.CommClause
|
||||
// *ast.ForStmt
|
||||
// *ast.RangeStmt
|
||||
//
|
||||
Scopes map[ast.Node]*Scope
|
||||
|
||||
// InitOrder is the list of package-level initializers in the order in which
|
||||
// they must be executed. Initializers referring to variables related by an
|
||||
// initialization dependency appear in topological order, the others appear
|
||||
// in source order. Variables without an initialization expression do not
|
||||
// appear in this list.
|
||||
InitOrder []*Initializer
|
||||
}
|
||||
|
||||
// TypeOf returns the type of expression e, or nil if not found.
|
||||
// Precondition: the Types, Uses and Defs maps are populated.
|
||||
//
|
||||
func (info *Info) TypeOf(e ast.Expr) Type {
|
||||
if t, ok := info.Types[e]; ok {
|
||||
return t.Type
|
||||
}
|
||||
if id, _ := e.(*ast.Ident); id != nil {
|
||||
if obj := info.ObjectOf(id); obj != nil {
|
||||
return obj.Type()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ObjectOf returns the object denoted by the specified id,
|
||||
// or nil if not found.
|
||||
//
|
||||
// If id is an anonymous struct field, ObjectOf returns the field (*Var)
|
||||
// it uses, not the type (*TypeName) it defines.
|
||||
//
|
||||
// Precondition: the Uses and Defs maps are populated.
|
||||
//
|
||||
func (info *Info) ObjectOf(id *ast.Ident) Object {
|
||||
if obj := info.Defs[id]; obj != nil {
|
||||
return obj
|
||||
}
|
||||
return info.Uses[id]
|
||||
}
|
||||
|
||||
// TypeAndValue reports the type and value (for constants)
|
||||
// of the corresponding expression.
|
||||
type TypeAndValue struct {
|
||||
mode operandMode
|
||||
Type Type
|
||||
Value constant.Value
|
||||
}
|
||||
|
||||
// TODO(gri) Consider eliminating the IsVoid predicate. Instead, report
|
||||
// "void" values as regular values but with the empty tuple type.
|
||||
|
||||
// IsVoid reports whether the corresponding expression
|
||||
// is a function call without results.
|
||||
func (tv TypeAndValue) IsVoid() bool {
|
||||
return tv.mode == novalue
|
||||
}
|
||||
|
||||
// IsType reports whether the corresponding expression specifies a type.
|
||||
func (tv TypeAndValue) IsType() bool {
|
||||
return tv.mode == typexpr
|
||||
}
|
||||
|
||||
// IsBuiltin reports whether the corresponding expression denotes
|
||||
// a (possibly parenthesized) built-in function.
|
||||
func (tv TypeAndValue) IsBuiltin() bool {
|
||||
return tv.mode == builtin
|
||||
}
|
||||
|
||||
// IsValue reports whether the corresponding expression is a value.
|
||||
// Builtins are not considered values. Constant values have a non-
|
||||
// nil Value.
|
||||
func (tv TypeAndValue) IsValue() bool {
|
||||
switch tv.mode {
|
||||
case constant_, variable, mapindex, value, commaok:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsNil reports whether the corresponding expression denotes the
|
||||
// predeclared value nil.
|
||||
func (tv TypeAndValue) IsNil() bool {
|
||||
return tv.mode == value && tv.Type == Typ[UntypedNil]
|
||||
}
|
||||
|
||||
// Addressable reports whether the corresponding expression
|
||||
// is addressable (https://golang.org/ref/spec#Address_operators).
|
||||
func (tv TypeAndValue) Addressable() bool {
|
||||
return tv.mode == variable
|
||||
}
|
||||
|
||||
// Assignable reports whether the corresponding expression
|
||||
// is assignable to (provided a value of the right type).
|
||||
func (tv TypeAndValue) Assignable() bool {
|
||||
return tv.mode == variable || tv.mode == mapindex
|
||||
}
|
||||
|
||||
// HasOk reports whether the corresponding expression may be
|
||||
// used on the lhs of a comma-ok assignment.
|
||||
func (tv TypeAndValue) HasOk() bool {
|
||||
return tv.mode == commaok || tv.mode == mapindex
|
||||
}
|
||||
|
||||
// An Initializer describes a package-level variable, or a list of variables in case
|
||||
// of a multi-valued initialization expression, and the corresponding initialization
|
||||
// expression.
|
||||
type Initializer struct {
|
||||
Lhs []*Var // var Lhs = Rhs
|
||||
Rhs ast.Expr
|
||||
}
|
||||
|
||||
func (init *Initializer) String() string {
|
||||
var buf bytes.Buffer
|
||||
for i, lhs := range init.Lhs {
|
||||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
buf.WriteString(lhs.Name())
|
||||
}
|
||||
buf.WriteString(" = ")
|
||||
WriteExpr(&buf, init.Rhs)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// Check type-checks a package and returns the resulting package object and
|
||||
// the first error if any. Additionally, if info != nil, Check populates each
|
||||
// of the non-nil maps in the Info struct.
|
||||
//
|
||||
// The package is marked as complete if no errors occurred, otherwise it is
|
||||
// incomplete. See Config.Error for controlling behavior in the presence of
|
||||
// errors.
|
||||
//
|
||||
// The package is specified by a list of *ast.Files and corresponding
|
||||
// file set, and the package path the package is identified with.
|
||||
// The clean path must not be empty or dot (".").
|
||||
func (conf *Config) Check(path string, fset *token.FileSet, files []*ast.File, info *Info) (*Package, error) {
|
||||
pkg := NewPackage(path, "")
|
||||
return pkg, NewChecker(conf, fset, pkg, info).Files(files)
|
||||
}
|
||||
|
||||
// AssertableTo reports whether a value of type V can be asserted to have type T.
|
||||
func AssertableTo(V *Interface, T Type) bool {
|
||||
m, _ := assertableTo(V, T)
|
||||
return m == nil
|
||||
}
|
||||
|
||||
// AssignableTo reports whether a value of type V is assignable to a variable of type T.
|
||||
func AssignableTo(V, T Type) bool {
|
||||
x := operand{mode: value, typ: V}
|
||||
return x.assignableTo(nil, T, nil) // config not needed for non-constant x
|
||||
}
|
||||
|
||||
// ConvertibleTo reports whether a value of type V is convertible to a value of type T.
|
||||
func ConvertibleTo(V, T Type) bool {
|
||||
x := operand{mode: value, typ: V}
|
||||
return x.convertibleTo(nil, T) // config not needed for non-constant x
|
||||
}
|
||||
|
||||
// Implements reports whether type V implements interface T.
|
||||
func Implements(V Type, T *Interface) bool {
|
||||
f, _ := MissingMethod(V, T, true)
|
||||
return f == nil
|
||||
}
|
335
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/assignments.go
generated
vendored
335
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/assignments.go
generated
vendored
@ -1,335 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements initialization and assignment checks.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// assignment reports whether x can be assigned to a variable of type T,
|
||||
// if necessary by attempting to convert untyped values to the appropriate
|
||||
// type. context describes the context in which the assignment takes place.
|
||||
// Use T == nil to indicate assignment to an untyped blank identifier.
|
||||
// x.mode is set to invalid if the assignment failed.
|
||||
func (check *Checker) assignment(x *operand, T Type, context string) {
|
||||
check.singleValue(x)
|
||||
|
||||
switch x.mode {
|
||||
case invalid:
|
||||
return // error reported before
|
||||
case constant_, variable, mapindex, value, commaok:
|
||||
// ok
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
|
||||
if isUntyped(x.typ) {
|
||||
target := T
|
||||
// spec: "If an untyped constant is assigned to a variable of interface
|
||||
// type or the blank identifier, the constant is first converted to type
|
||||
// bool, rune, int, float64, complex128 or string respectively, depending
|
||||
// on whether the value is a boolean, rune, integer, floating-point, complex,
|
||||
// or string constant."
|
||||
if T == nil || IsInterface(T) {
|
||||
if T == nil && x.typ == Typ[UntypedNil] {
|
||||
check.errorf(x.pos(), "use of untyped nil in %s", context)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
target = Default(x.typ)
|
||||
}
|
||||
check.convertUntyped(x, target)
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
}
|
||||
// x.typ is typed
|
||||
|
||||
// spec: "If a left-hand side is the blank identifier, any typed or
|
||||
// non-constant value except for the predeclared identifier nil may
|
||||
// be assigned to it."
|
||||
if T == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if reason := ""; !x.assignableTo(check.conf, T, &reason) {
|
||||
if reason != "" {
|
||||
check.errorf(x.pos(), "cannot use %s as %s value in %s: %s", x, T, context, reason)
|
||||
} else {
|
||||
check.errorf(x.pos(), "cannot use %s as %s value in %s", x, T, context)
|
||||
}
|
||||
x.mode = invalid
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) initConst(lhs *Const, x *operand) {
|
||||
if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
|
||||
if lhs.typ == nil {
|
||||
lhs.typ = Typ[Invalid]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// rhs must be a constant
|
||||
if x.mode != constant_ {
|
||||
check.errorf(x.pos(), "%s is not constant", x)
|
||||
if lhs.typ == nil {
|
||||
lhs.typ = Typ[Invalid]
|
||||
}
|
||||
return
|
||||
}
|
||||
assert(isConstType(x.typ))
|
||||
|
||||
// If the lhs doesn't have a type yet, use the type of x.
|
||||
if lhs.typ == nil {
|
||||
lhs.typ = x.typ
|
||||
}
|
||||
|
||||
check.assignment(x, lhs.typ, "constant declaration")
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
||||
lhs.val = x.val
|
||||
}
|
||||
|
||||
func (check *Checker) initVar(lhs *Var, x *operand, context string) Type {
|
||||
if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
|
||||
if lhs.typ == nil {
|
||||
lhs.typ = Typ[Invalid]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the lhs doesn't have a type yet, use the type of x.
|
||||
if lhs.typ == nil {
|
||||
typ := x.typ
|
||||
if isUntyped(typ) {
|
||||
// convert untyped types to default types
|
||||
if typ == Typ[UntypedNil] {
|
||||
check.errorf(x.pos(), "use of untyped nil in %s", context)
|
||||
lhs.typ = Typ[Invalid]
|
||||
return nil
|
||||
}
|
||||
typ = Default(typ)
|
||||
}
|
||||
lhs.typ = typ
|
||||
}
|
||||
|
||||
check.assignment(x, lhs.typ, context)
|
||||
if x.mode == invalid {
|
||||
return nil
|
||||
}
|
||||
|
||||
return x.typ
|
||||
}
|
||||
|
||||
func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
|
||||
if x.mode == invalid || x.typ == Typ[Invalid] {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Determine if the lhs is a (possibly parenthesized) identifier.
|
||||
ident, _ := unparen(lhs).(*ast.Ident)
|
||||
|
||||
// Don't evaluate lhs if it is the blank identifier.
|
||||
if ident != nil && ident.Name == "_" {
|
||||
check.recordDef(ident, nil)
|
||||
check.assignment(x, nil, "assignment to _ identifier")
|
||||
if x.mode == invalid {
|
||||
return nil
|
||||
}
|
||||
return x.typ
|
||||
}
|
||||
|
||||
// If the lhs is an identifier denoting a variable v, this assignment
|
||||
// is not a 'use' of v. Remember current value of v.used and restore
|
||||
// after evaluating the lhs via check.expr.
|
||||
var v *Var
|
||||
var v_used bool
|
||||
if ident != nil {
|
||||
if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
|
||||
// It's ok to mark non-local variables, but ignore variables
|
||||
// from other packages to avoid potential race conditions with
|
||||
// dot-imported variables.
|
||||
if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
|
||||
v = w
|
||||
v_used = v.used
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var z operand
|
||||
check.expr(&z, lhs)
|
||||
if v != nil {
|
||||
v.used = v_used // restore v.used
|
||||
}
|
||||
|
||||
if z.mode == invalid || z.typ == Typ[Invalid] {
|
||||
return nil
|
||||
}
|
||||
|
||||
// spec: "Each left-hand side operand must be addressable, a map index
|
||||
// expression, or the blank identifier. Operands may be parenthesized."
|
||||
switch z.mode {
|
||||
case invalid:
|
||||
return nil
|
||||
case variable, mapindex:
|
||||
// ok
|
||||
default:
|
||||
if sel, ok := z.expr.(*ast.SelectorExpr); ok {
|
||||
var op operand
|
||||
check.expr(&op, sel.X)
|
||||
if op.mode == mapindex {
|
||||
check.errorf(z.pos(), "cannot assign to struct field %s in map", ExprString(z.expr))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
check.errorf(z.pos(), "cannot assign to %s", &z)
|
||||
return nil
|
||||
}
|
||||
|
||||
check.assignment(x, z.typ, "assignment")
|
||||
if x.mode == invalid {
|
||||
return nil
|
||||
}
|
||||
|
||||
return x.typ
|
||||
}
|
||||
|
||||
// If returnPos is valid, initVars is called to type-check the assignment of
|
||||
// return expressions, and returnPos is the position of the return statement.
|
||||
func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos) {
|
||||
l := len(lhs)
|
||||
get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())
|
||||
if get == nil || l != r {
|
||||
// invalidate lhs and use rhs
|
||||
for _, obj := range lhs {
|
||||
if obj.typ == nil {
|
||||
obj.typ = Typ[Invalid]
|
||||
}
|
||||
}
|
||||
if get == nil {
|
||||
return // error reported by unpack
|
||||
}
|
||||
check.useGetter(get, r)
|
||||
if returnPos.IsValid() {
|
||||
check.errorf(returnPos, "wrong number of return values (want %d, got %d)", l, r)
|
||||
return
|
||||
}
|
||||
check.errorf(rhs[0].Pos(), "cannot initialize %d variables with %d values", l, r)
|
||||
return
|
||||
}
|
||||
|
||||
context := "assignment"
|
||||
if returnPos.IsValid() {
|
||||
context = "return statement"
|
||||
}
|
||||
|
||||
var x operand
|
||||
if commaOk {
|
||||
var a [2]Type
|
||||
for i := range a {
|
||||
get(&x, i)
|
||||
a[i] = check.initVar(lhs[i], &x, context)
|
||||
}
|
||||
check.recordCommaOkTypes(rhs[0], a)
|
||||
return
|
||||
}
|
||||
|
||||
for i, lhs := range lhs {
|
||||
get(&x, i)
|
||||
check.initVar(lhs, &x, context)
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) assignVars(lhs, rhs []ast.Expr) {
|
||||
l := len(lhs)
|
||||
get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2)
|
||||
if get == nil {
|
||||
check.useLHS(lhs...)
|
||||
return // error reported by unpack
|
||||
}
|
||||
if l != r {
|
||||
check.useGetter(get, r)
|
||||
check.errorf(rhs[0].Pos(), "cannot assign %d values to %d variables", r, l)
|
||||
return
|
||||
}
|
||||
|
||||
var x operand
|
||||
if commaOk {
|
||||
var a [2]Type
|
||||
for i := range a {
|
||||
get(&x, i)
|
||||
a[i] = check.assignVar(lhs[i], &x)
|
||||
}
|
||||
check.recordCommaOkTypes(rhs[0], a)
|
||||
return
|
||||
}
|
||||
|
||||
for i, lhs := range lhs {
|
||||
get(&x, i)
|
||||
check.assignVar(lhs, &x)
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
|
||||
scope := check.scope
|
||||
|
||||
// collect lhs variables
|
||||
var newVars []*Var
|
||||
var lhsVars = make([]*Var, len(lhs))
|
||||
for i, lhs := range lhs {
|
||||
var obj *Var
|
||||
if ident, _ := lhs.(*ast.Ident); ident != nil {
|
||||
// Use the correct obj if the ident is redeclared. The
|
||||
// variable's scope starts after the declaration; so we
|
||||
// must use Scope.Lookup here and call Scope.Insert
|
||||
// (via check.declare) later.
|
||||
name := ident.Name
|
||||
if alt := scope.Lookup(name); alt != nil {
|
||||
// redeclared object must be a variable
|
||||
if alt, _ := alt.(*Var); alt != nil {
|
||||
obj = alt
|
||||
} else {
|
||||
check.errorf(lhs.Pos(), "cannot assign to %s", lhs)
|
||||
}
|
||||
check.recordUse(ident, alt)
|
||||
} else {
|
||||
// declare new variable, possibly a blank (_) variable
|
||||
obj = NewVar(ident.Pos(), check.pkg, name, nil)
|
||||
if name != "_" {
|
||||
newVars = append(newVars, obj)
|
||||
}
|
||||
check.recordDef(ident, obj)
|
||||
}
|
||||
} else {
|
||||
check.errorf(lhs.Pos(), "cannot declare %s", lhs)
|
||||
}
|
||||
if obj == nil {
|
||||
obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
|
||||
}
|
||||
lhsVars[i] = obj
|
||||
}
|
||||
|
||||
check.initVars(lhsVars, rhs, token.NoPos)
|
||||
|
||||
// declare new variables
|
||||
if len(newVars) > 0 {
|
||||
// spec: "The scope of a constant or variable identifier declared inside
|
||||
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
|
||||
// for short variable declarations) and ends at the end of the innermost
|
||||
// containing block."
|
||||
scopePos := rhs[len(rhs)-1].End()
|
||||
for _, obj := range newVars {
|
||||
check.declare(scope, nil, obj, scopePos) // recordObject already called
|
||||
}
|
||||
} else {
|
||||
check.softErrorf(pos, "no new variables on left side of :=")
|
||||
}
|
||||
}
|
670
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/builtins.go
generated
vendored
670
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/builtins.go
generated
vendored
@ -1,670 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements typechecking of builtin function calls.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// builtin type-checks a call to the built-in specified by id and
|
||||
// returns true if the call is valid, with *x holding the result;
|
||||
// but x.expr is not set. If the call is invalid, the result is
|
||||
// false, and *x is undefined.
|
||||
//
|
||||
func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ bool) {
|
||||
// append is the only built-in that permits the use of ... for the last argument
|
||||
bin := predeclaredFuncs[id]
|
||||
if call.Ellipsis.IsValid() && id != _Append {
|
||||
check.invalidOp(call.Ellipsis, "invalid use of ... with built-in %s", bin.name)
|
||||
check.use(call.Args...)
|
||||
return
|
||||
}
|
||||
|
||||
// For len(x) and cap(x) we need to know if x contains any function calls or
|
||||
// receive operations. Save/restore current setting and set hasCallOrRecv to
|
||||
// false for the evaluation of x so that we can check it afterwards.
|
||||
// Note: We must do this _before_ calling unpack because unpack evaluates the
|
||||
// first argument before we even call arg(x, 0)!
|
||||
if id == _Len || id == _Cap {
|
||||
defer func(b bool) {
|
||||
check.hasCallOrRecv = b
|
||||
}(check.hasCallOrRecv)
|
||||
check.hasCallOrRecv = false
|
||||
}
|
||||
|
||||
// determine actual arguments
|
||||
var arg getter
|
||||
nargs := len(call.Args)
|
||||
switch id {
|
||||
default:
|
||||
// make argument getter
|
||||
arg, nargs, _ = unpack(func(x *operand, i int) { check.multiExpr(x, call.Args[i]) }, nargs, false)
|
||||
if arg == nil {
|
||||
return
|
||||
}
|
||||
// evaluate first argument, if present
|
||||
if nargs > 0 {
|
||||
arg(x, 0)
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
}
|
||||
case _Make, _New, _Offsetof, _Trace:
|
||||
// arguments require special handling
|
||||
}
|
||||
|
||||
// check argument count
|
||||
{
|
||||
msg := ""
|
||||
if nargs < bin.nargs {
|
||||
msg = "not enough"
|
||||
} else if !bin.variadic && nargs > bin.nargs {
|
||||
msg = "too many"
|
||||
}
|
||||
if msg != "" {
|
||||
check.invalidOp(call.Rparen, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
switch id {
|
||||
case _Append:
|
||||
// append(s S, x ...T) S, where T is the element type of S
|
||||
// spec: "The variadic function append appends zero or more values x to s of type
|
||||
// S, which must be a slice type, and returns the resulting slice, also of type S.
|
||||
// The values x are passed to a parameter of type ...T where T is the element type
|
||||
// of S and the respective parameter passing rules apply."
|
||||
S := x.typ
|
||||
var T Type
|
||||
if s, _ := S.Underlying().(*Slice); s != nil {
|
||||
T = s.elem
|
||||
} else {
|
||||
check.invalidArg(x.pos(), "%s is not a slice", x)
|
||||
return
|
||||
}
|
||||
|
||||
// remember arguments that have been evaluated already
|
||||
alist := []operand{*x}
|
||||
|
||||
// spec: "As a special case, append also accepts a first argument assignable
|
||||
// to type []byte with a second argument of string type followed by ... .
|
||||
// This form appends the bytes of the string.
|
||||
if nargs == 2 && call.Ellipsis.IsValid() && x.assignableTo(check.conf, NewSlice(universeByte), nil) {
|
||||
arg(x, 1)
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
if isString(x.typ) {
|
||||
if check.Types != nil {
|
||||
sig := makeSig(S, S, x.typ)
|
||||
sig.variadic = true
|
||||
check.recordBuiltinType(call.Fun, sig)
|
||||
}
|
||||
x.mode = value
|
||||
x.typ = S
|
||||
break
|
||||
}
|
||||
alist = append(alist, *x)
|
||||
// fallthrough
|
||||
}
|
||||
|
||||
// check general case by creating custom signature
|
||||
sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature
|
||||
sig.variadic = true
|
||||
check.arguments(x, call, sig, func(x *operand, i int) {
|
||||
// only evaluate arguments that have not been evaluated before
|
||||
if i < len(alist) {
|
||||
*x = alist[i]
|
||||
return
|
||||
}
|
||||
arg(x, i)
|
||||
}, nargs)
|
||||
// ok to continue even if check.arguments reported errors
|
||||
|
||||
x.mode = value
|
||||
x.typ = S
|
||||
if check.Types != nil {
|
||||
check.recordBuiltinType(call.Fun, sig)
|
||||
}
|
||||
|
||||
case _Cap, _Len:
|
||||
// cap(x)
|
||||
// len(x)
|
||||
mode := invalid
|
||||
var typ Type
|
||||
var val constant.Value
|
||||
switch typ = implicitArrayDeref(x.typ.Underlying()); t := typ.(type) {
|
||||
case *Basic:
|
||||
if isString(t) && id == _Len {
|
||||
if x.mode == constant_ {
|
||||
mode = constant_
|
||||
val = constant.MakeInt64(int64(len(constant.StringVal(x.val))))
|
||||
} else {
|
||||
mode = value
|
||||
}
|
||||
}
|
||||
|
||||
case *Array:
|
||||
mode = value
|
||||
// spec: "The expressions len(s) and cap(s) are constants
|
||||
// if the type of s is an array or pointer to an array and
|
||||
// the expression s does not contain channel receives or
|
||||
// function calls; in this case s is not evaluated."
|
||||
if !check.hasCallOrRecv {
|
||||
mode = constant_
|
||||
if t.len >= 0 {
|
||||
val = constant.MakeInt64(t.len)
|
||||
} else {
|
||||
val = constant.MakeUnknown()
|
||||
}
|
||||
}
|
||||
|
||||
case *Slice, *Chan:
|
||||
mode = value
|
||||
|
||||
case *Map:
|
||||
if id == _Len {
|
||||
mode = value
|
||||
}
|
||||
}
|
||||
|
||||
if mode == invalid {
|
||||
check.invalidArg(x.pos(), "%s for %s", x, bin.name)
|
||||
return
|
||||
}
|
||||
|
||||
x.mode = mode
|
||||
x.typ = Typ[Int]
|
||||
x.val = val
|
||||
if check.Types != nil && mode != constant_ {
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ, typ))
|
||||
}
|
||||
|
||||
case _Close:
|
||||
// close(c)
|
||||
c, _ := x.typ.Underlying().(*Chan)
|
||||
if c == nil {
|
||||
check.invalidArg(x.pos(), "%s is not a channel", x)
|
||||
return
|
||||
}
|
||||
if c.dir == RecvOnly {
|
||||
check.invalidArg(x.pos(), "%s must not be a receive-only channel", x)
|
||||
return
|
||||
}
|
||||
|
||||
x.mode = novalue
|
||||
if check.Types != nil {
|
||||
check.recordBuiltinType(call.Fun, makeSig(nil, c))
|
||||
}
|
||||
|
||||
case _Complex:
|
||||
// complex(x, y floatT) complexT
|
||||
var y operand
|
||||
arg(&y, 1)
|
||||
if y.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
||||
// convert or check untyped arguments
|
||||
d := 0
|
||||
if isUntyped(x.typ) {
|
||||
d |= 1
|
||||
}
|
||||
if isUntyped(y.typ) {
|
||||
d |= 2
|
||||
}
|
||||
switch d {
|
||||
case 0:
|
||||
// x and y are typed => nothing to do
|
||||
case 1:
|
||||
// only x is untyped => convert to type of y
|
||||
check.convertUntyped(x, y.typ)
|
||||
case 2:
|
||||
// only y is untyped => convert to type of x
|
||||
check.convertUntyped(&y, x.typ)
|
||||
case 3:
|
||||
// x and y are untyped =>
|
||||
// 1) if both are constants, convert them to untyped
|
||||
// floating-point numbers if possible,
|
||||
// 2) if one of them is not constant (possible because
|
||||
// it contains a shift that is yet untyped), convert
|
||||
// both of them to float64 since they must have the
|
||||
// same type to succeed (this will result in an error
|
||||
// because shifts of floats are not permitted)
|
||||
if x.mode == constant_ && y.mode == constant_ {
|
||||
toFloat := func(x *operand) {
|
||||
if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 {
|
||||
x.typ = Typ[UntypedFloat]
|
||||
}
|
||||
}
|
||||
toFloat(x)
|
||||
toFloat(&y)
|
||||
} else {
|
||||
check.convertUntyped(x, Typ[Float64])
|
||||
check.convertUntyped(&y, Typ[Float64])
|
||||
// x and y should be invalid now, but be conservative
|
||||
// and check below
|
||||
}
|
||||
}
|
||||
if x.mode == invalid || y.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
||||
// both argument types must be identical
|
||||
if !Identical(x.typ, y.typ) {
|
||||
check.invalidArg(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
|
||||
return
|
||||
}
|
||||
|
||||
// the argument types must be of floating-point type
|
||||
if !isFloat(x.typ) {
|
||||
check.invalidArg(x.pos(), "arguments have type %s, expected floating-point", x.typ)
|
||||
return
|
||||
}
|
||||
|
||||
// if both arguments are constants, the result is a constant
|
||||
if x.mode == constant_ && y.mode == constant_ {
|
||||
x.val = constant.BinaryOp(constant.ToFloat(x.val), token.ADD, constant.MakeImag(constant.ToFloat(y.val)))
|
||||
} else {
|
||||
x.mode = value
|
||||
}
|
||||
|
||||
// determine result type
|
||||
var res BasicKind
|
||||
switch x.typ.Underlying().(*Basic).kind {
|
||||
case Float32:
|
||||
res = Complex64
|
||||
case Float64:
|
||||
res = Complex128
|
||||
case UntypedFloat:
|
||||
res = UntypedComplex
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
resTyp := Typ[res]
|
||||
|
||||
if check.Types != nil && x.mode != constant_ {
|
||||
check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ))
|
||||
}
|
||||
|
||||
x.typ = resTyp
|
||||
|
||||
case _Copy:
|
||||
// copy(x, y []T) int
|
||||
var dst Type
|
||||
if t, _ := x.typ.Underlying().(*Slice); t != nil {
|
||||
dst = t.elem
|
||||
}
|
||||
|
||||
var y operand
|
||||
arg(&y, 1)
|
||||
if y.mode == invalid {
|
||||
return
|
||||
}
|
||||
var src Type
|
||||
switch t := y.typ.Underlying().(type) {
|
||||
case *Basic:
|
||||
if isString(y.typ) {
|
||||
src = universeByte
|
||||
}
|
||||
case *Slice:
|
||||
src = t.elem
|
||||
}
|
||||
|
||||
if dst == nil || src == nil {
|
||||
check.invalidArg(x.pos(), "copy expects slice arguments; found %s and %s", x, &y)
|
||||
return
|
||||
}
|
||||
|
||||
if !Identical(dst, src) {
|
||||
check.invalidArg(x.pos(), "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src)
|
||||
return
|
||||
}
|
||||
|
||||
if check.Types != nil {
|
||||
check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ))
|
||||
}
|
||||
x.mode = value
|
||||
x.typ = Typ[Int]
|
||||
|
||||
case _Delete:
|
||||
// delete(m, k)
|
||||
m, _ := x.typ.Underlying().(*Map)
|
||||
if m == nil {
|
||||
check.invalidArg(x.pos(), "%s is not a map", x)
|
||||
return
|
||||
}
|
||||
arg(x, 1) // k
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
||||
if !x.assignableTo(check.conf, m.key, nil) {
|
||||
check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.key)
|
||||
return
|
||||
}
|
||||
|
||||
x.mode = novalue
|
||||
if check.Types != nil {
|
||||
check.recordBuiltinType(call.Fun, makeSig(nil, m, m.key))
|
||||
}
|
||||
|
||||
case _Imag, _Real:
|
||||
// imag(complexT) floatT
|
||||
// real(complexT) floatT
|
||||
|
||||
// convert or check untyped argument
|
||||
if isUntyped(x.typ) {
|
||||
if x.mode == constant_ {
|
||||
// an untyped constant number can alway be considered
|
||||
// as a complex constant
|
||||
if isNumeric(x.typ) {
|
||||
x.typ = Typ[UntypedComplex]
|
||||
}
|
||||
} else {
|
||||
// an untyped non-constant argument may appear if
|
||||
// it contains a (yet untyped non-constant) shift
|
||||
// expression: convert it to complex128 which will
|
||||
// result in an error (shift of complex value)
|
||||
check.convertUntyped(x, Typ[Complex128])
|
||||
// x should be invalid now, but be conservative and check
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the argument must be of complex type
|
||||
if !isComplex(x.typ) {
|
||||
check.invalidArg(x.pos(), "argument has type %s, expected complex type", x.typ)
|
||||
return
|
||||
}
|
||||
|
||||
// if the argument is a constant, the result is a constant
|
||||
if x.mode == constant_ {
|
||||
if id == _Real {
|
||||
x.val = constant.Real(x.val)
|
||||
} else {
|
||||
x.val = constant.Imag(x.val)
|
||||
}
|
||||
} else {
|
||||
x.mode = value
|
||||
}
|
||||
|
||||
// determine result type
|
||||
var res BasicKind
|
||||
switch x.typ.Underlying().(*Basic).kind {
|
||||
case Complex64:
|
||||
res = Float32
|
||||
case Complex128:
|
||||
res = Float64
|
||||
case UntypedComplex:
|
||||
res = UntypedFloat
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
resTyp := Typ[res]
|
||||
|
||||
if check.Types != nil && x.mode != constant_ {
|
||||
check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ))
|
||||
}
|
||||
|
||||
x.typ = resTyp
|
||||
|
||||
case _Make:
|
||||
// make(T, n)
|
||||
// make(T, n, m)
|
||||
// (no argument evaluated yet)
|
||||
arg0 := call.Args[0]
|
||||
T := check.typ(arg0)
|
||||
if T == Typ[Invalid] {
|
||||
return
|
||||
}
|
||||
|
||||
var min int // minimum number of arguments
|
||||
switch T.Underlying().(type) {
|
||||
case *Slice:
|
||||
min = 2
|
||||
case *Map, *Chan:
|
||||
min = 1
|
||||
default:
|
||||
check.invalidArg(arg0.Pos(), "cannot make %s; type must be slice, map, or channel", arg0)
|
||||
return
|
||||
}
|
||||
if nargs < min || min+1 < nargs {
|
||||
check.errorf(call.Pos(), "%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
|
||||
return
|
||||
}
|
||||
var sizes []int64 // constant integer arguments, if any
|
||||
for _, arg := range call.Args[1:] {
|
||||
if s, ok := check.index(arg, -1); ok && s >= 0 {
|
||||
sizes = append(sizes, s)
|
||||
}
|
||||
}
|
||||
if len(sizes) == 2 && sizes[0] > sizes[1] {
|
||||
check.invalidArg(call.Args[1].Pos(), "length and capacity swapped")
|
||||
// safe to continue
|
||||
}
|
||||
x.mode = value
|
||||
x.typ = T
|
||||
if check.Types != nil {
|
||||
params := [...]Type{T, Typ[Int], Typ[Int]}
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ, params[:1+len(sizes)]...))
|
||||
}
|
||||
|
||||
case _New:
|
||||
// new(T)
|
||||
// (no argument evaluated yet)
|
||||
T := check.typ(call.Args[0])
|
||||
if T == Typ[Invalid] {
|
||||
return
|
||||
}
|
||||
|
||||
x.mode = value
|
||||
x.typ = &Pointer{base: T}
|
||||
if check.Types != nil {
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
|
||||
}
|
||||
|
||||
case _Panic:
|
||||
// panic(x)
|
||||
check.assignment(x, &emptyInterface, "argument to panic")
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
||||
x.mode = novalue
|
||||
if check.Types != nil {
|
||||
check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface))
|
||||
}
|
||||
|
||||
case _Print, _Println:
|
||||
// print(x, y, ...)
|
||||
// println(x, y, ...)
|
||||
var params []Type
|
||||
if nargs > 0 {
|
||||
params = make([]Type, nargs)
|
||||
for i := 0; i < nargs; i++ {
|
||||
if i > 0 {
|
||||
arg(x, i) // first argument already evaluated
|
||||
}
|
||||
check.assignment(x, nil, "argument to "+predeclaredFuncs[id].name)
|
||||
if x.mode == invalid {
|
||||
// TODO(gri) "use" all arguments?
|
||||
return
|
||||
}
|
||||
params[i] = x.typ
|
||||
}
|
||||
}
|
||||
|
||||
x.mode = novalue
|
||||
if check.Types != nil {
|
||||
check.recordBuiltinType(call.Fun, makeSig(nil, params...))
|
||||
}
|
||||
|
||||
case _Recover:
|
||||
// recover() interface{}
|
||||
x.mode = value
|
||||
x.typ = &emptyInterface
|
||||
if check.Types != nil {
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ))
|
||||
}
|
||||
|
||||
case _Alignof:
|
||||
// unsafe.Alignof(x T) uintptr
|
||||
check.assignment(x, nil, "argument to unsafe.Alignof")
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
||||
x.mode = constant_
|
||||
x.val = constant.MakeInt64(check.conf.alignof(x.typ))
|
||||
x.typ = Typ[Uintptr]
|
||||
// result is constant - no need to record signature
|
||||
|
||||
case _Offsetof:
|
||||
// unsafe.Offsetof(x T) uintptr, where x must be a selector
|
||||
// (no argument evaluated yet)
|
||||
arg0 := call.Args[0]
|
||||
selx, _ := unparen(arg0).(*ast.SelectorExpr)
|
||||
if selx == nil {
|
||||
check.invalidArg(arg0.Pos(), "%s is not a selector expression", arg0)
|
||||
check.use(arg0)
|
||||
return
|
||||
}
|
||||
|
||||
check.expr(x, selx.X)
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
||||
base := derefStructPtr(x.typ)
|
||||
sel := selx.Sel.Name
|
||||
obj, index, indirect := LookupFieldOrMethod(base, false, check.pkg, sel)
|
||||
switch obj.(type) {
|
||||
case nil:
|
||||
check.invalidArg(x.pos(), "%s has no single field %s", base, sel)
|
||||
return
|
||||
case *Func:
|
||||
// TODO(gri) Using derefStructPtr may result in methods being found
|
||||
// that don't actually exist. An error either way, but the error
|
||||
// message is confusing. See: https://play.golang.org/p/al75v23kUy ,
|
||||
// but go/types reports: "invalid argument: x.m is a method value".
|
||||
check.invalidArg(arg0.Pos(), "%s is a method value", arg0)
|
||||
return
|
||||
}
|
||||
if indirect {
|
||||
check.invalidArg(x.pos(), "field %s is embedded via a pointer in %s", sel, base)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(gri) Should we pass x.typ instead of base (and indirect report if derefStructPtr indirected)?
|
||||
check.recordSelection(selx, FieldVal, base, obj, index, false)
|
||||
|
||||
offs := check.conf.offsetof(base, index)
|
||||
x.mode = constant_
|
||||
x.val = constant.MakeInt64(offs)
|
||||
x.typ = Typ[Uintptr]
|
||||
// result is constant - no need to record signature
|
||||
|
||||
case _Sizeof:
|
||||
// unsafe.Sizeof(x T) uintptr
|
||||
check.assignment(x, nil, "argument to unsafe.Sizeof")
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
||||
x.mode = constant_
|
||||
x.val = constant.MakeInt64(check.conf.sizeof(x.typ))
|
||||
x.typ = Typ[Uintptr]
|
||||
// result is constant - no need to record signature
|
||||
|
||||
case _Assert:
|
||||
// assert(pred) causes a typechecker error if pred is false.
|
||||
// The result of assert is the value of pred if there is no error.
|
||||
// Note: assert is only available in self-test mode.
|
||||
if x.mode != constant_ || !isBoolean(x.typ) {
|
||||
check.invalidArg(x.pos(), "%s is not a boolean constant", x)
|
||||
return
|
||||
}
|
||||
if x.val.Kind() != constant.Bool {
|
||||
check.errorf(x.pos(), "internal error: value of %s should be a boolean constant", x)
|
||||
return
|
||||
}
|
||||
if !constant.BoolVal(x.val) {
|
||||
check.errorf(call.Pos(), "%v failed", call)
|
||||
// compile-time assertion failure - safe to continue
|
||||
}
|
||||
// result is constant - no need to record signature
|
||||
|
||||
case _Trace:
|
||||
// trace(x, y, z, ...) dumps the positions, expressions, and
|
||||
// values of its arguments. The result of trace is the value
|
||||
// of the first argument.
|
||||
// Note: trace is only available in self-test mode.
|
||||
// (no argument evaluated yet)
|
||||
if nargs == 0 {
|
||||
check.dump("%s: trace() without arguments", call.Pos())
|
||||
x.mode = novalue
|
||||
break
|
||||
}
|
||||
var t operand
|
||||
x1 := x
|
||||
for _, arg := range call.Args {
|
||||
check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T))
|
||||
check.dump("%s: %s", x1.pos(), x1)
|
||||
x1 = &t // use incoming x only for first argument
|
||||
}
|
||||
// trace is only available in test mode - no need to record signature
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// makeSig makes a signature for the given argument and result types.
|
||||
// Default types are used for untyped arguments, and res may be nil.
|
||||
func makeSig(res Type, args ...Type) *Signature {
|
||||
list := make([]*Var, len(args))
|
||||
for i, param := range args {
|
||||
list[i] = NewVar(token.NoPos, nil, "", Default(param))
|
||||
}
|
||||
params := NewTuple(list...)
|
||||
var result *Tuple
|
||||
if res != nil {
|
||||
assert(!isUntyped(res))
|
||||
result = NewTuple(NewVar(token.NoPos, nil, "", res))
|
||||
}
|
||||
return &Signature{params: params, results: result}
|
||||
}
|
||||
|
||||
// implicitArrayDeref returns A if typ is of the form *A and A is an array;
|
||||
// otherwise it returns typ.
|
||||
//
|
||||
func implicitArrayDeref(typ Type) Type {
|
||||
if p, ok := typ.(*Pointer); ok {
|
||||
if a, ok := p.base.Underlying().(*Array); ok {
|
||||
return a
|
||||
}
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
// unparen returns e with any enclosing parentheses stripped.
|
||||
func unparen(e ast.Expr) ast.Expr {
|
||||
for {
|
||||
p, ok := e.(*ast.ParenExpr)
|
||||
if !ok {
|
||||
return e
|
||||
}
|
||||
e = p.X
|
||||
}
|
||||
}
|
478
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/call.go
generated
vendored
478
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/call.go
generated
vendored
@ -1,478 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements typechecking of call and selector expressions.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
|
||||
check.exprOrType(x, e.Fun)
|
||||
|
||||
switch x.mode {
|
||||
case invalid:
|
||||
check.use(e.Args...)
|
||||
x.mode = invalid
|
||||
x.expr = e
|
||||
return statement
|
||||
|
||||
case typexpr:
|
||||
// conversion
|
||||
T := x.typ
|
||||
x.mode = invalid
|
||||
switch n := len(e.Args); n {
|
||||
case 0:
|
||||
check.errorf(e.Rparen, "missing argument in conversion to %s", T)
|
||||
case 1:
|
||||
check.expr(x, e.Args[0])
|
||||
if x.mode != invalid {
|
||||
check.conversion(x, T)
|
||||
}
|
||||
default:
|
||||
check.errorf(e.Args[n-1].Pos(), "too many arguments in conversion to %s", T)
|
||||
}
|
||||
x.expr = e
|
||||
return conversion
|
||||
|
||||
case builtin:
|
||||
id := x.id
|
||||
if !check.builtin(x, e, id) {
|
||||
x.mode = invalid
|
||||
}
|
||||
x.expr = e
|
||||
// a non-constant result implies a function call
|
||||
if x.mode != invalid && x.mode != constant_ {
|
||||
check.hasCallOrRecv = true
|
||||
}
|
||||
return predeclaredFuncs[id].kind
|
||||
|
||||
default:
|
||||
// function/method call
|
||||
sig, _ := x.typ.Underlying().(*Signature)
|
||||
if sig == nil {
|
||||
check.invalidOp(x.pos(), "cannot call non-function %s", x)
|
||||
x.mode = invalid
|
||||
x.expr = e
|
||||
return statement
|
||||
}
|
||||
|
||||
arg, n, _ := unpack(func(x *operand, i int) { check.multiExpr(x, e.Args[i]) }, len(e.Args), false)
|
||||
if arg != nil {
|
||||
check.arguments(x, e, sig, arg, n)
|
||||
} else {
|
||||
x.mode = invalid
|
||||
}
|
||||
|
||||
// determine result
|
||||
switch sig.results.Len() {
|
||||
case 0:
|
||||
x.mode = novalue
|
||||
case 1:
|
||||
x.mode = value
|
||||
x.typ = sig.results.vars[0].typ // unpack tuple
|
||||
default:
|
||||
x.mode = value
|
||||
x.typ = sig.results
|
||||
}
|
||||
|
||||
x.expr = e
|
||||
check.hasCallOrRecv = true
|
||||
|
||||
return statement
|
||||
}
|
||||
}
|
||||
|
||||
// use type-checks each argument.
|
||||
// Useful to make sure expressions are evaluated
|
||||
// (and variables are "used") in the presence of other errors.
|
||||
// The arguments may be nil.
|
||||
func (check *Checker) use(arg ...ast.Expr) {
|
||||
var x operand
|
||||
for _, e := range arg {
|
||||
// The nil check below is necessary since certain AST fields
|
||||
// may legally be nil (e.g., the ast.SliceExpr.High field).
|
||||
if e != nil {
|
||||
check.rawExpr(&x, e, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// useLHS is like use, but doesn't "use" top-level identifiers.
|
||||
// It should be called instead of use if the arguments are
|
||||
// expressions on the lhs of an assignment.
|
||||
// The arguments must not be nil.
|
||||
func (check *Checker) useLHS(arg ...ast.Expr) {
|
||||
var x operand
|
||||
for _, e := range arg {
|
||||
// If the lhs is an identifier denoting a variable v, this assignment
|
||||
// is not a 'use' of v. Remember current value of v.used and restore
|
||||
// after evaluating the lhs via check.rawExpr.
|
||||
var v *Var
|
||||
var v_used bool
|
||||
if ident, _ := unparen(e).(*ast.Ident); ident != nil {
|
||||
// never type-check the blank name on the lhs
|
||||
if ident.Name == "_" {
|
||||
continue
|
||||
}
|
||||
if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
|
||||
// It's ok to mark non-local variables, but ignore variables
|
||||
// from other packages to avoid potential race conditions with
|
||||
// dot-imported variables.
|
||||
if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
|
||||
v = w
|
||||
v_used = v.used
|
||||
}
|
||||
}
|
||||
}
|
||||
check.rawExpr(&x, e, nil)
|
||||
if v != nil {
|
||||
v.used = v_used // restore v.used
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// useGetter is like use, but takes a getter instead of a list of expressions.
|
||||
// It should be called instead of use if a getter is present to avoid repeated
|
||||
// evaluation of the first argument (since the getter was likely obtained via
|
||||
// unpack, which may have evaluated the first argument already).
|
||||
func (check *Checker) useGetter(get getter, n int) {
|
||||
var x operand
|
||||
for i := 0; i < n; i++ {
|
||||
get(&x, i)
|
||||
}
|
||||
}
|
||||
|
||||
// A getter sets x as the i'th operand, where 0 <= i < n and n is the total
|
||||
// number of operands (context-specific, and maintained elsewhere). A getter
|
||||
// type-checks the i'th operand; the details of the actual check are getter-
|
||||
// specific.
|
||||
type getter func(x *operand, i int)
|
||||
|
||||
// unpack takes a getter get and a number of operands n. If n == 1, unpack
|
||||
// calls the incoming getter for the first operand. If that operand is
|
||||
// invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a
|
||||
// function call, or a comma-ok expression and allowCommaOk is set, the result
|
||||
// is a new getter and operand count providing access to the function results,
|
||||
// or comma-ok values, respectively. The third result value reports if it
|
||||
// is indeed the comma-ok case. In all other cases, the incoming getter and
|
||||
// operand count are returned unchanged, and the third result value is false.
|
||||
//
|
||||
// In other words, if there's exactly one operand that - after type-checking
|
||||
// by calling get - stands for multiple operands, the resulting getter provides
|
||||
// access to those operands instead.
|
||||
//
|
||||
// If the returned getter is called at most once for a given operand index i
|
||||
// (including i == 0), that operand is guaranteed to cause only one call of
|
||||
// the incoming getter with that i.
|
||||
//
|
||||
func unpack(get getter, n int, allowCommaOk bool) (getter, int, bool) {
|
||||
if n != 1 {
|
||||
// zero or multiple values
|
||||
return get, n, false
|
||||
}
|
||||
// possibly result of an n-valued function call or comma,ok value
|
||||
var x0 operand
|
||||
get(&x0, 0)
|
||||
if x0.mode == invalid {
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
if t, ok := x0.typ.(*Tuple); ok {
|
||||
// result of an n-valued function call
|
||||
return func(x *operand, i int) {
|
||||
x.mode = value
|
||||
x.expr = x0.expr
|
||||
x.typ = t.At(i).typ
|
||||
}, t.Len(), false
|
||||
}
|
||||
|
||||
if x0.mode == mapindex || x0.mode == commaok {
|
||||
// comma-ok value
|
||||
if allowCommaOk {
|
||||
a := [2]Type{x0.typ, Typ[UntypedBool]}
|
||||
return func(x *operand, i int) {
|
||||
x.mode = value
|
||||
x.expr = x0.expr
|
||||
x.typ = a[i]
|
||||
}, 2, true
|
||||
}
|
||||
x0.mode = value
|
||||
}
|
||||
|
||||
// single value
|
||||
return func(x *operand, i int) {
|
||||
if i != 0 {
|
||||
unreachable()
|
||||
}
|
||||
*x = x0
|
||||
}, 1, false
|
||||
}
|
||||
|
||||
// arguments checks argument passing for the call with the given signature.
|
||||
// The arg function provides the operand for the i'th argument.
|
||||
func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature, arg getter, n int) {
|
||||
if call.Ellipsis.IsValid() {
|
||||
// last argument is of the form x...
|
||||
if !sig.variadic {
|
||||
check.errorf(call.Ellipsis, "cannot use ... in call to non-variadic %s", call.Fun)
|
||||
check.useGetter(arg, n)
|
||||
return
|
||||
}
|
||||
if len(call.Args) == 1 && n > 1 {
|
||||
// f()... is not permitted if f() is multi-valued
|
||||
check.errorf(call.Ellipsis, "cannot use ... with %d-valued %s", n, call.Args[0])
|
||||
check.useGetter(arg, n)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate arguments
|
||||
for i := 0; i < n; i++ {
|
||||
arg(x, i)
|
||||
if x.mode != invalid {
|
||||
var ellipsis token.Pos
|
||||
if i == n-1 && call.Ellipsis.IsValid() {
|
||||
ellipsis = call.Ellipsis
|
||||
}
|
||||
check.argument(call.Fun, sig, i, x, ellipsis)
|
||||
}
|
||||
}
|
||||
|
||||
// check argument count
|
||||
if sig.variadic {
|
||||
// a variadic function accepts an "empty"
|
||||
// last argument: count one extra
|
||||
n++
|
||||
}
|
||||
if n < sig.params.Len() {
|
||||
check.errorf(call.Rparen, "too few arguments in call to %s", call.Fun)
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
|
||||
// argument checks passing of argument x to the i'th parameter of the given signature.
|
||||
// If ellipsis is valid, the argument is followed by ... at that position in the call.
|
||||
func (check *Checker) argument(fun ast.Expr, sig *Signature, i int, x *operand, ellipsis token.Pos) {
|
||||
check.singleValue(x)
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
||||
n := sig.params.Len()
|
||||
|
||||
// determine parameter type
|
||||
var typ Type
|
||||
switch {
|
||||
case i < n:
|
||||
typ = sig.params.vars[i].typ
|
||||
case sig.variadic:
|
||||
typ = sig.params.vars[n-1].typ
|
||||
if debug {
|
||||
if _, ok := typ.(*Slice); !ok {
|
||||
check.dump("%s: expected unnamed slice type, got %s", sig.params.vars[n-1].Pos(), typ)
|
||||
}
|
||||
}
|
||||
default:
|
||||
check.errorf(x.pos(), "too many arguments")
|
||||
return
|
||||
}
|
||||
|
||||
if ellipsis.IsValid() {
|
||||
// argument is of the form x... and x is single-valued
|
||||
if i != n-1 {
|
||||
check.errorf(ellipsis, "can only use ... with matching parameter")
|
||||
return
|
||||
}
|
||||
if _, ok := x.typ.Underlying().(*Slice); !ok && x.typ != Typ[UntypedNil] { // see issue #18268
|
||||
check.errorf(x.pos(), "cannot use %s as parameter of type %s", x, typ)
|
||||
return
|
||||
}
|
||||
} else if sig.variadic && i >= n-1 {
|
||||
// use the variadic parameter slice's element type
|
||||
typ = typ.(*Slice).elem
|
||||
}
|
||||
|
||||
check.assignment(x, typ, check.sprintf("argument to %s", fun))
|
||||
}
|
||||
|
||||
func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
|
||||
// these must be declared before the "goto Error" statements
|
||||
var (
|
||||
obj Object
|
||||
index []int
|
||||
indirect bool
|
||||
)
|
||||
|
||||
sel := e.Sel.Name
|
||||
// If the identifier refers to a package, handle everything here
|
||||
// so we don't need a "package" mode for operands: package names
|
||||
// can only appear in qualified identifiers which are mapped to
|
||||
// selector expressions.
|
||||
if ident, ok := e.X.(*ast.Ident); ok {
|
||||
_, obj := check.scope.LookupParent(ident.Name, check.pos)
|
||||
if pname, _ := obj.(*PkgName); pname != nil {
|
||||
assert(pname.pkg == check.pkg)
|
||||
check.recordUse(ident, pname)
|
||||
pname.used = true
|
||||
pkg := pname.imported
|
||||
exp := pkg.scope.Lookup(sel)
|
||||
if exp == nil {
|
||||
if !pkg.fake {
|
||||
check.errorf(e.Pos(), "%s not declared by package %s", sel, pkg.name)
|
||||
}
|
||||
goto Error
|
||||
}
|
||||
if !exp.Exported() {
|
||||
check.errorf(e.Pos(), "%s not exported by package %s", sel, pkg.name)
|
||||
// ok to continue
|
||||
}
|
||||
check.recordUse(e.Sel, exp)
|
||||
|
||||
// Simplified version of the code for *ast.Idents:
|
||||
// - imported objects are always fully initialized
|
||||
switch exp := exp.(type) {
|
||||
case *Const:
|
||||
assert(exp.Val() != nil)
|
||||
x.mode = constant_
|
||||
x.typ = exp.typ
|
||||
x.val = exp.val
|
||||
case *TypeName:
|
||||
x.mode = typexpr
|
||||
x.typ = exp.typ
|
||||
case *Var:
|
||||
x.mode = variable
|
||||
x.typ = exp.typ
|
||||
case *Func:
|
||||
x.mode = value
|
||||
x.typ = exp.typ
|
||||
case *Builtin:
|
||||
x.mode = builtin
|
||||
x.typ = exp.typ
|
||||
x.id = exp.id
|
||||
default:
|
||||
check.dump("unexpected object %v", exp)
|
||||
unreachable()
|
||||
}
|
||||
x.expr = e
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
check.exprOrType(x, e.X)
|
||||
if x.mode == invalid {
|
||||
goto Error
|
||||
}
|
||||
|
||||
obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
|
||||
if obj == nil {
|
||||
switch {
|
||||
case index != nil:
|
||||
// TODO(gri) should provide actual type where the conflict happens
|
||||
check.invalidOp(e.Pos(), "ambiguous selector %s", sel)
|
||||
case indirect:
|
||||
check.invalidOp(e.Pos(), "%s is not in method set of %s", sel, x.typ)
|
||||
default:
|
||||
check.invalidOp(e.Pos(), "%s has no field or method %s", x, sel)
|
||||
}
|
||||
goto Error
|
||||
}
|
||||
|
||||
if x.mode == typexpr {
|
||||
// method expression
|
||||
m, _ := obj.(*Func)
|
||||
if m == nil {
|
||||
check.invalidOp(e.Pos(), "%s has no method %s", x, sel)
|
||||
goto Error
|
||||
}
|
||||
|
||||
check.recordSelection(e, MethodExpr, x.typ, m, index, indirect)
|
||||
|
||||
// the receiver type becomes the type of the first function
|
||||
// argument of the method expression's function type
|
||||
var params []*Var
|
||||
sig := m.typ.(*Signature)
|
||||
if sig.params != nil {
|
||||
params = sig.params.vars
|
||||
}
|
||||
x.mode = value
|
||||
x.typ = &Signature{
|
||||
params: NewTuple(append([]*Var{NewVar(token.NoPos, check.pkg, "", x.typ)}, params...)...),
|
||||
results: sig.results,
|
||||
variadic: sig.variadic,
|
||||
}
|
||||
|
||||
check.addDeclDep(m)
|
||||
|
||||
} else {
|
||||
// regular selector
|
||||
switch obj := obj.(type) {
|
||||
case *Var:
|
||||
check.recordSelection(e, FieldVal, x.typ, obj, index, indirect)
|
||||
if x.mode == variable || indirect {
|
||||
x.mode = variable
|
||||
} else {
|
||||
x.mode = value
|
||||
}
|
||||
x.typ = obj.typ
|
||||
|
||||
case *Func:
|
||||
// TODO(gri) If we needed to take into account the receiver's
|
||||
// addressability, should we report the type &(x.typ) instead?
|
||||
check.recordSelection(e, MethodVal, x.typ, obj, index, indirect)
|
||||
|
||||
if debug {
|
||||
// Verify that LookupFieldOrMethod and MethodSet.Lookup agree.
|
||||
typ := x.typ
|
||||
if x.mode == variable {
|
||||
// If typ is not an (unnamed) pointer or an interface,
|
||||
// use *typ instead, because the method set of *typ
|
||||
// includes the methods of typ.
|
||||
// Variables are addressable, so we can always take their
|
||||
// address.
|
||||
if _, ok := typ.(*Pointer); !ok && !IsInterface(typ) {
|
||||
typ = &Pointer{base: typ}
|
||||
}
|
||||
}
|
||||
// If we created a synthetic pointer type above, we will throw
|
||||
// away the method set computed here after use.
|
||||
// TODO(gri) Method set computation should probably always compute
|
||||
// both, the value and the pointer receiver method set and represent
|
||||
// them in a single structure.
|
||||
// TODO(gri) Consider also using a method set cache for the lifetime
|
||||
// of checker once we rely on MethodSet lookup instead of individual
|
||||
// lookup.
|
||||
mset := NewMethodSet(typ)
|
||||
if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj {
|
||||
check.dump("%s: (%s).%v -> %s", e.Pos(), typ, obj.name, m)
|
||||
check.dump("%s\n", mset)
|
||||
panic("method sets and lookup don't agree")
|
||||
}
|
||||
}
|
||||
|
||||
x.mode = value
|
||||
|
||||
// remove receiver
|
||||
sig := *obj.typ.(*Signature)
|
||||
sig.recv = nil
|
||||
x.typ = &sig
|
||||
|
||||
check.addDeclDep(obj)
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
}
|
||||
|
||||
// everything went well
|
||||
x.expr = e
|
||||
return
|
||||
|
||||
Error:
|
||||
x.mode = invalid
|
||||
x.expr = e
|
||||
}
|
371
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/check.go
generated
vendored
371
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/check.go
generated
vendored
@ -1,371 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements the Check function, which drives type-checking.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// debugging/development support
|
||||
const (
|
||||
debug = false // leave on during development
|
||||
trace = false // turn on for detailed type resolution traces
|
||||
)
|
||||
|
||||
// If Strict is set, the type-checker enforces additional
|
||||
// rules not specified by the Go 1 spec, but which will
|
||||
// catch guaranteed run-time errors if the respective
|
||||
// code is executed. In other words, programs passing in
|
||||
// Strict mode are Go 1 compliant, but not all Go 1 programs
|
||||
// will pass in Strict mode. The additional rules are:
|
||||
//
|
||||
// - A type assertion x.(T) where T is an interface type
|
||||
// is invalid if any (statically known) method that exists
|
||||
// for both x and T have different signatures.
|
||||
//
|
||||
const strict = false
|
||||
|
||||
// exprInfo stores information about an untyped expression.
|
||||
type exprInfo struct {
|
||||
isLhs bool // expression is lhs operand of a shift with delayed type-check
|
||||
mode operandMode
|
||||
typ *Basic
|
||||
val constant.Value // constant value; or nil (if not a constant)
|
||||
}
|
||||
|
||||
// funcInfo stores the information required for type-checking a function.
|
||||
type funcInfo struct {
|
||||
name string // for debugging/tracing only
|
||||
decl *declInfo // for cycle detection
|
||||
sig *Signature
|
||||
body *ast.BlockStmt
|
||||
}
|
||||
|
||||
// A context represents the context within which an object is type-checked.
|
||||
type context struct {
|
||||
decl *declInfo // package-level declaration whose init expression/function body is checked
|
||||
scope *Scope // top-most scope for lookups
|
||||
iota constant.Value // value of iota in a constant declaration; nil otherwise
|
||||
sig *Signature // function signature if inside a function; nil otherwise
|
||||
hasLabel bool // set if a function makes use of labels (only ~1% of functions); unused outside functions
|
||||
hasCallOrRecv bool // set if an expression contains a function call or channel receive operation
|
||||
}
|
||||
|
||||
// An importKey identifies an imported package by import path and source directory
|
||||
// (directory containing the file containing the import). In practice, the directory
|
||||
// may always be the same, or may not matter. Given an (import path, directory), an
|
||||
// importer must always return the same package (but given two different import paths,
|
||||
// an importer may still return the same package by mapping them to the same package
|
||||
// paths).
|
||||
type importKey struct {
|
||||
path, dir string
|
||||
}
|
||||
|
||||
// A Checker maintains the state of the type checker.
|
||||
// It must be created with NewChecker.
|
||||
type Checker struct {
|
||||
// package information
|
||||
// (initialized by NewChecker, valid for the life-time of checker)
|
||||
conf *Config
|
||||
fset *token.FileSet
|
||||
pkg *Package
|
||||
*Info
|
||||
objMap map[Object]*declInfo // maps package-level object to declaration info
|
||||
impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
|
||||
|
||||
// information collected during type-checking of a set of package files
|
||||
// (initialized by Files, valid only for the duration of check.Files;
|
||||
// maps and lists are allocated on demand)
|
||||
files []*ast.File // package files
|
||||
unusedDotImports map[*Scope]map[*Package]token.Pos // positions of unused dot-imported packages for each file scope
|
||||
|
||||
firstErr error // first error encountered
|
||||
methods map[string][]*Func // maps type names to associated methods
|
||||
untyped map[ast.Expr]exprInfo // map of expressions without final type
|
||||
funcs []funcInfo // list of functions to type-check
|
||||
delayed []func() // delayed checks requiring fully setup types
|
||||
|
||||
// context within which the current object is type-checked
|
||||
// (valid only for the duration of type-checking a specific object)
|
||||
context
|
||||
pos token.Pos // if valid, identifiers are looked up as if at position pos (used by Eval)
|
||||
|
||||
// debugging
|
||||
indent int // indentation for tracing
|
||||
}
|
||||
|
||||
// addUnusedImport adds the position of a dot-imported package
|
||||
// pkg to the map of dot imports for the given file scope.
|
||||
func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, pos token.Pos) {
|
||||
mm := check.unusedDotImports
|
||||
if mm == nil {
|
||||
mm = make(map[*Scope]map[*Package]token.Pos)
|
||||
check.unusedDotImports = mm
|
||||
}
|
||||
m := mm[scope]
|
||||
if m == nil {
|
||||
m = make(map[*Package]token.Pos)
|
||||
mm[scope] = m
|
||||
}
|
||||
m[pkg] = pos
|
||||
}
|
||||
|
||||
// addDeclDep adds the dependency edge (check.decl -> to) if check.decl exists
|
||||
func (check *Checker) addDeclDep(to Object) {
|
||||
from := check.decl
|
||||
if from == nil {
|
||||
return // not in a package-level init expression
|
||||
}
|
||||
if _, found := check.objMap[to]; !found {
|
||||
return // to is not a package-level object
|
||||
}
|
||||
from.addDep(to)
|
||||
}
|
||||
|
||||
func (check *Checker) assocMethod(tname string, meth *Func) {
|
||||
m := check.methods
|
||||
if m == nil {
|
||||
m = make(map[string][]*Func)
|
||||
check.methods = m
|
||||
}
|
||||
m[tname] = append(m[tname], meth)
|
||||
}
|
||||
|
||||
func (check *Checker) rememberUntyped(e ast.Expr, lhs bool, mode operandMode, typ *Basic, val constant.Value) {
|
||||
m := check.untyped
|
||||
if m == nil {
|
||||
m = make(map[ast.Expr]exprInfo)
|
||||
check.untyped = m
|
||||
}
|
||||
m[e] = exprInfo{lhs, mode, typ, val}
|
||||
}
|
||||
|
||||
func (check *Checker) later(name string, decl *declInfo, sig *Signature, body *ast.BlockStmt) {
|
||||
check.funcs = append(check.funcs, funcInfo{name, decl, sig, body})
|
||||
}
|
||||
|
||||
func (check *Checker) delay(f func()) {
|
||||
check.delayed = append(check.delayed, f)
|
||||
}
|
||||
|
||||
// NewChecker returns a new Checker instance for a given package.
|
||||
// Package files may be added incrementally via checker.Files.
|
||||
func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Checker {
|
||||
// make sure we have a configuration
|
||||
if conf == nil {
|
||||
conf = new(Config)
|
||||
}
|
||||
|
||||
// make sure we have an info struct
|
||||
if info == nil {
|
||||
info = new(Info)
|
||||
}
|
||||
|
||||
return &Checker{
|
||||
conf: conf,
|
||||
fset: fset,
|
||||
pkg: pkg,
|
||||
Info: info,
|
||||
objMap: make(map[Object]*declInfo),
|
||||
impMap: make(map[importKey]*Package),
|
||||
}
|
||||
}
|
||||
|
||||
// initFiles initializes the files-specific portion of checker.
|
||||
// The provided files must all belong to the same package.
|
||||
func (check *Checker) initFiles(files []*ast.File) {
|
||||
// start with a clean slate (check.Files may be called multiple times)
|
||||
check.files = nil
|
||||
check.unusedDotImports = nil
|
||||
|
||||
check.firstErr = nil
|
||||
check.methods = nil
|
||||
check.untyped = nil
|
||||
check.funcs = nil
|
||||
check.delayed = nil
|
||||
|
||||
// determine package name and collect valid files
|
||||
pkg := check.pkg
|
||||
for _, file := range files {
|
||||
switch name := file.Name.Name; pkg.name {
|
||||
case "":
|
||||
if name != "_" {
|
||||
pkg.name = name
|
||||
} else {
|
||||
check.errorf(file.Name.Pos(), "invalid package name _")
|
||||
}
|
||||
fallthrough
|
||||
|
||||
case name:
|
||||
check.files = append(check.files, file)
|
||||
|
||||
default:
|
||||
check.errorf(file.Package, "package %s; expected %s", name, pkg.name)
|
||||
// ignore this file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A bailout panic is used for early termination.
|
||||
type bailout struct{}
|
||||
|
||||
func (check *Checker) handleBailout(err *error) {
|
||||
switch p := recover().(type) {
|
||||
case nil, bailout:
|
||||
// normal return or early exit
|
||||
*err = check.firstErr
|
||||
default:
|
||||
// re-panic
|
||||
panic(p)
|
||||
}
|
||||
}
|
||||
|
||||
// Files checks the provided files as part of the checker's package.
|
||||
func (check *Checker) Files(files []*ast.File) error { return check.checkFiles(files) }
|
||||
|
||||
func (check *Checker) checkFiles(files []*ast.File) (err error) {
|
||||
defer check.handleBailout(&err)
|
||||
|
||||
check.initFiles(files)
|
||||
|
||||
check.collectObjects()
|
||||
|
||||
check.packageObjects(check.resolveOrder())
|
||||
|
||||
check.functionBodies()
|
||||
|
||||
check.initOrder()
|
||||
|
||||
if !check.conf.DisableUnusedImportCheck {
|
||||
check.unusedImports()
|
||||
}
|
||||
|
||||
// perform delayed checks
|
||||
for _, f := range check.delayed {
|
||||
f()
|
||||
}
|
||||
|
||||
check.recordUntyped()
|
||||
|
||||
check.pkg.complete = true
|
||||
return
|
||||
}
|
||||
|
||||
func (check *Checker) recordUntyped() {
|
||||
if !debug && check.Types == nil {
|
||||
return // nothing to do
|
||||
}
|
||||
|
||||
for x, info := range check.untyped {
|
||||
if debug && isTyped(info.typ) {
|
||||
check.dump("%s: %s (type %s) is typed", x.Pos(), x, info.typ)
|
||||
unreachable()
|
||||
}
|
||||
check.recordTypeAndValue(x, info.mode, info.typ, info.val)
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type, val constant.Value) {
|
||||
assert(x != nil)
|
||||
assert(typ != nil)
|
||||
if mode == invalid {
|
||||
return // omit
|
||||
}
|
||||
assert(typ != nil)
|
||||
if mode == constant_ {
|
||||
assert(val != nil)
|
||||
assert(typ == Typ[Invalid] || isConstType(typ))
|
||||
}
|
||||
if m := check.Types; m != nil {
|
||||
m[x] = TypeAndValue{mode, typ, val}
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) recordBuiltinType(f ast.Expr, sig *Signature) {
|
||||
// f must be a (possibly parenthesized) identifier denoting a built-in
|
||||
// (built-ins in package unsafe always produce a constant result and
|
||||
// we don't record their signatures, so we don't see qualified idents
|
||||
// here): record the signature for f and possible children.
|
||||
for {
|
||||
check.recordTypeAndValue(f, builtin, sig, nil)
|
||||
switch p := f.(type) {
|
||||
case *ast.Ident:
|
||||
return // we're done
|
||||
case *ast.ParenExpr:
|
||||
f = p.X
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) recordCommaOkTypes(x ast.Expr, a [2]Type) {
|
||||
assert(x != nil)
|
||||
if a[0] == nil || a[1] == nil {
|
||||
return
|
||||
}
|
||||
assert(isTyped(a[0]) && isTyped(a[1]) && isBoolean(a[1]))
|
||||
if m := check.Types; m != nil {
|
||||
for {
|
||||
tv := m[x]
|
||||
assert(tv.Type != nil) // should have been recorded already
|
||||
pos := x.Pos()
|
||||
tv.Type = NewTuple(
|
||||
NewVar(pos, check.pkg, "", a[0]),
|
||||
NewVar(pos, check.pkg, "", a[1]),
|
||||
)
|
||||
m[x] = tv
|
||||
// if x is a parenthesized expression (p.X), update p.X
|
||||
p, _ := x.(*ast.ParenExpr)
|
||||
if p == nil {
|
||||
break
|
||||
}
|
||||
x = p.X
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) recordDef(id *ast.Ident, obj Object) {
|
||||
assert(id != nil)
|
||||
if m := check.Defs; m != nil {
|
||||
m[id] = obj
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) recordUse(id *ast.Ident, obj Object) {
|
||||
assert(id != nil)
|
||||
assert(obj != nil)
|
||||
if m := check.Uses; m != nil {
|
||||
m[id] = obj
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) recordImplicit(node ast.Node, obj Object) {
|
||||
assert(node != nil)
|
||||
assert(obj != nil)
|
||||
if m := check.Implicits; m != nil {
|
||||
m[node] = obj
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) recordSelection(x *ast.SelectorExpr, kind SelectionKind, recv Type, obj Object, index []int, indirect bool) {
|
||||
assert(obj != nil && (recv == nil || len(index) > 0))
|
||||
check.recordUse(x.Sel, obj)
|
||||
if m := check.Selections; m != nil {
|
||||
m[x] = &Selection{kind, recv, obj, index, indirect}
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) recordScope(node ast.Node, scope *Scope) {
|
||||
assert(node != nil)
|
||||
assert(scope != nil)
|
||||
if m := check.Scopes; m != nil {
|
||||
m[node] = scope
|
||||
}
|
||||
}
|
160
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/conversions.go
generated
vendored
160
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/conversions.go
generated
vendored
@ -1,160 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements typechecking of conversions.
|
||||
|
||||
package types
|
||||
|
||||
import "go/constant"
|
||||
|
||||
// Conversion type-checks the conversion T(x).
|
||||
// The result is in x.
|
||||
func (check *Checker) conversion(x *operand, T Type) {
|
||||
constArg := x.mode == constant_
|
||||
|
||||
var ok bool
|
||||
switch {
|
||||
case constArg && isConstType(T):
|
||||
// constant conversion
|
||||
switch t := T.Underlying().(*Basic); {
|
||||
case representableConst(x.val, check.conf, t, &x.val):
|
||||
ok = true
|
||||
case isInteger(x.typ) && isString(t):
|
||||
codepoint := int64(-1)
|
||||
if i, ok := constant.Int64Val(x.val); ok {
|
||||
codepoint = i
|
||||
}
|
||||
// If codepoint < 0 the absolute value is too large (or unknown) for
|
||||
// conversion. This is the same as converting any other out-of-range
|
||||
// value - let string(codepoint) do the work.
|
||||
x.val = constant.MakeString(string(codepoint))
|
||||
ok = true
|
||||
}
|
||||
case x.convertibleTo(check.conf, T):
|
||||
// non-constant conversion
|
||||
x.mode = value
|
||||
ok = true
|
||||
}
|
||||
|
||||
if !ok {
|
||||
check.errorf(x.pos(), "cannot convert %s to %s", x, T)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
|
||||
// The conversion argument types are final. For untyped values the
|
||||
// conversion provides the type, per the spec: "A constant may be
|
||||
// given a type explicitly by a constant declaration or conversion,...".
|
||||
if isUntyped(x.typ) {
|
||||
final := T
|
||||
// - For conversions to interfaces, use the argument's default type.
|
||||
// - For conversions of untyped constants to non-constant types, also
|
||||
// use the default type (e.g., []byte("foo") should report string
|
||||
// not []byte as type for the constant "foo").
|
||||
// - Keep untyped nil for untyped nil arguments.
|
||||
// - For integer to string conversions, keep the argument type.
|
||||
// (See also the TODO below.)
|
||||
if IsInterface(T) || constArg && !isConstType(T) {
|
||||
final = Default(x.typ)
|
||||
} else if isInteger(x.typ) && isString(T) {
|
||||
final = x.typ
|
||||
}
|
||||
check.updateExprType(x.expr, final, true)
|
||||
}
|
||||
|
||||
x.typ = T
|
||||
}
|
||||
|
||||
// TODO(gri) convertibleTo checks if T(x) is valid. It assumes that the type
|
||||
// of x is fully known, but that's not the case for say string(1<<s + 1.0):
|
||||
// Here, the type of 1<<s + 1.0 will be UntypedFloat which will lead to the
|
||||
// (correct!) refusal of the conversion. But the reported error is essentially
|
||||
// "cannot convert untyped float value to string", yet the correct error (per
|
||||
// the spec) is that we cannot shift a floating-point value: 1 in 1<<s should
|
||||
// be converted to UntypedFloat because of the addition of 1.0. Fixing this
|
||||
// is tricky because we'd have to run updateExprType on the argument first.
|
||||
// (Issue #21982.)
|
||||
|
||||
func (x *operand) convertibleTo(conf *Config, T Type) bool {
|
||||
// "x is assignable to T"
|
||||
if x.assignableTo(conf, T, nil) {
|
||||
return true
|
||||
}
|
||||
|
||||
// "x's type and T have identical underlying types if tags are ignored"
|
||||
V := x.typ
|
||||
Vu := V.Underlying()
|
||||
Tu := T.Underlying()
|
||||
if IdenticalIgnoreTags(Vu, Tu) {
|
||||
return true
|
||||
}
|
||||
|
||||
// "x's type and T are unnamed pointer types and their pointer base types
|
||||
// have identical underlying types if tags are ignored"
|
||||
if V, ok := V.(*Pointer); ok {
|
||||
if T, ok := T.(*Pointer); ok {
|
||||
if IdenticalIgnoreTags(V.base.Underlying(), T.base.Underlying()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "x's type and T are both integer or floating point types"
|
||||
if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// "x's type and T are both complex types"
|
||||
if isComplex(V) && isComplex(T) {
|
||||
return true
|
||||
}
|
||||
|
||||
// "x is an integer or a slice of bytes or runes and T is a string type"
|
||||
if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) {
|
||||
return true
|
||||
}
|
||||
|
||||
// "x is a string and T is a slice of bytes or runes"
|
||||
if isString(V) && isBytesOrRunes(Tu) {
|
||||
return true
|
||||
}
|
||||
|
||||
// package unsafe:
|
||||
// "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"
|
||||
if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) {
|
||||
return true
|
||||
}
|
||||
// "and vice versa"
|
||||
if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func isUintptr(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.kind == Uintptr
|
||||
}
|
||||
|
||||
func isUnsafePointer(typ Type) bool {
|
||||
// TODO(gri): Is this (typ.Underlying() instead of just typ) correct?
|
||||
// The spec does not say so, but gc claims it is. See also
|
||||
// issue 6326.
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.kind == UnsafePointer
|
||||
}
|
||||
|
||||
func isPointer(typ Type) bool {
|
||||
_, ok := typ.Underlying().(*Pointer)
|
||||
return ok
|
||||
}
|
||||
|
||||
func isBytesOrRunes(typ Type) bool {
|
||||
if s, ok := typ.(*Slice); ok {
|
||||
t, ok := s.elem.Underlying().(*Basic)
|
||||
return ok && (t.kind == Byte || t.kind == Rune)
|
||||
}
|
||||
return false
|
||||
}
|
467
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/decl.go
generated
vendored
467
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/decl.go
generated
vendored
@ -1,467 +0,0 @@
|
||||
// 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 types
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
func (check *Checker) reportAltDecl(obj Object) {
|
||||
if pos := obj.Pos(); pos.IsValid() {
|
||||
// We use "other" rather than "previous" here because
|
||||
// the first declaration seen may not be textually
|
||||
// earlier in the source.
|
||||
check.errorf(pos, "\tother declaration of %s", obj.Name()) // secondary error, \t indented
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) declare(scope *Scope, id *ast.Ident, obj Object, pos token.Pos) {
|
||||
// spec: "The blank identifier, represented by the underscore
|
||||
// character _, may be used in a declaration like any other
|
||||
// identifier but the declaration does not introduce a new
|
||||
// binding."
|
||||
if obj.Name() != "_" {
|
||||
if alt := scope.Insert(obj); alt != nil {
|
||||
check.errorf(obj.Pos(), "%s redeclared in this block", obj.Name())
|
||||
check.reportAltDecl(alt)
|
||||
return
|
||||
}
|
||||
obj.setScopePos(pos)
|
||||
}
|
||||
if id != nil {
|
||||
check.recordDef(id, obj)
|
||||
}
|
||||
}
|
||||
|
||||
// objDecl type-checks the declaration of obj in its respective (file) context.
|
||||
// See check.typ for the details on def and path.
|
||||
func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
|
||||
if obj.Type() != nil {
|
||||
return // already checked - nothing to do
|
||||
}
|
||||
|
||||
if trace {
|
||||
check.trace(obj.Pos(), "-- declaring %s", obj.Name())
|
||||
check.indent++
|
||||
defer func() {
|
||||
check.indent--
|
||||
check.trace(obj.Pos(), "=> %s", obj)
|
||||
}()
|
||||
}
|
||||
|
||||
d := check.objMap[obj]
|
||||
if d == nil {
|
||||
check.dump("%s: %s should have been declared", obj.Pos(), obj.Name())
|
||||
unreachable()
|
||||
}
|
||||
|
||||
// save/restore current context and setup object context
|
||||
defer func(ctxt context) {
|
||||
check.context = ctxt
|
||||
}(check.context)
|
||||
check.context = context{
|
||||
scope: d.file,
|
||||
}
|
||||
|
||||
// Const and var declarations must not have initialization
|
||||
// cycles. We track them by remembering the current declaration
|
||||
// in check.decl. Initialization expressions depending on other
|
||||
// consts, vars, or functions, add dependencies to the current
|
||||
// check.decl.
|
||||
switch obj := obj.(type) {
|
||||
case *Const:
|
||||
check.decl = d // new package-level const decl
|
||||
check.constDecl(obj, d.typ, d.init)
|
||||
case *Var:
|
||||
check.decl = d // new package-level var decl
|
||||
check.varDecl(obj, d.lhs, d.typ, d.init)
|
||||
case *TypeName:
|
||||
// invalid recursive types are detected via path
|
||||
check.typeDecl(obj, d.typ, def, path, d.alias)
|
||||
case *Func:
|
||||
// functions may be recursive - no need to track dependencies
|
||||
check.funcDecl(obj, d)
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
|
||||
assert(obj.typ == nil)
|
||||
|
||||
if obj.visited {
|
||||
obj.typ = Typ[Invalid]
|
||||
return
|
||||
}
|
||||
obj.visited = true
|
||||
|
||||
// use the correct value of iota
|
||||
assert(check.iota == nil)
|
||||
check.iota = obj.val
|
||||
defer func() { check.iota = nil }()
|
||||
|
||||
// provide valid constant value under all circumstances
|
||||
obj.val = constant.MakeUnknown()
|
||||
|
||||
// determine type, if any
|
||||
if typ != nil {
|
||||
t := check.typ(typ)
|
||||
if !isConstType(t) {
|
||||
// don't report an error if the type is an invalid C (defined) type
|
||||
// (issue #22090)
|
||||
if t.Underlying() != Typ[Invalid] {
|
||||
check.errorf(typ.Pos(), "invalid constant type %s", t)
|
||||
}
|
||||
obj.typ = Typ[Invalid]
|
||||
return
|
||||
}
|
||||
obj.typ = t
|
||||
}
|
||||
|
||||
// check initialization
|
||||
var x operand
|
||||
if init != nil {
|
||||
check.expr(&x, init)
|
||||
}
|
||||
check.initConst(obj, &x)
|
||||
}
|
||||
|
||||
func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
|
||||
assert(obj.typ == nil)
|
||||
|
||||
if obj.visited {
|
||||
obj.typ = Typ[Invalid]
|
||||
return
|
||||
}
|
||||
obj.visited = true
|
||||
|
||||
// var declarations cannot use iota
|
||||
assert(check.iota == nil)
|
||||
|
||||
// determine type, if any
|
||||
if typ != nil {
|
||||
obj.typ = check.typ(typ)
|
||||
// We cannot spread the type to all lhs variables if there
|
||||
// are more than one since that would mark them as checked
|
||||
// (see Checker.objDecl) and the assignment of init exprs,
|
||||
// if any, would not be checked.
|
||||
//
|
||||
// TODO(gri) If we have no init expr, we should distribute
|
||||
// a given type otherwise we need to re-evalate the type
|
||||
// expr for each lhs variable, leading to duplicate work.
|
||||
}
|
||||
|
||||
// check initialization
|
||||
if init == nil {
|
||||
if typ == nil {
|
||||
// error reported before by arityMatch
|
||||
obj.typ = Typ[Invalid]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if lhs == nil || len(lhs) == 1 {
|
||||
assert(lhs == nil || lhs[0] == obj)
|
||||
var x operand
|
||||
check.expr(&x, init)
|
||||
check.initVar(obj, &x, "variable declaration")
|
||||
return
|
||||
}
|
||||
|
||||
if debug {
|
||||
// obj must be one of lhs
|
||||
found := false
|
||||
for _, lhs := range lhs {
|
||||
if obj == lhs {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
panic("inconsistent lhs")
|
||||
}
|
||||
}
|
||||
|
||||
// We have multiple variables on the lhs and one init expr.
|
||||
// Make sure all variables have been given the same type if
|
||||
// one was specified, otherwise they assume the type of the
|
||||
// init expression values (was issue #15755).
|
||||
if typ != nil {
|
||||
for _, lhs := range lhs {
|
||||
lhs.typ = obj.typ
|
||||
}
|
||||
}
|
||||
|
||||
check.initVars(lhs, []ast.Expr{init}, token.NoPos)
|
||||
}
|
||||
|
||||
// underlying returns the underlying type of typ; possibly by following
|
||||
// forward chains of named types. Such chains only exist while named types
|
||||
// are incomplete.
|
||||
func underlying(typ Type) Type {
|
||||
for {
|
||||
n, _ := typ.(*Named)
|
||||
if n == nil {
|
||||
break
|
||||
}
|
||||
typ = n.underlying
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
func (n *Named) setUnderlying(typ Type) {
|
||||
if n != nil {
|
||||
n.underlying = typ
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, path []*TypeName, alias bool) {
|
||||
assert(obj.typ == nil)
|
||||
|
||||
// type declarations cannot use iota
|
||||
assert(check.iota == nil)
|
||||
|
||||
if alias {
|
||||
|
||||
obj.typ = Typ[Invalid]
|
||||
obj.typ = check.typExpr(typ, nil, append(path, obj))
|
||||
|
||||
} else {
|
||||
|
||||
named := &Named{obj: obj}
|
||||
def.setUnderlying(named)
|
||||
obj.typ = named // make sure recursive type declarations terminate
|
||||
|
||||
// determine underlying type of named
|
||||
check.typExpr(typ, named, append(path, obj))
|
||||
|
||||
// The underlying type of named may be itself a named type that is
|
||||
// incomplete:
|
||||
//
|
||||
// type (
|
||||
// A B
|
||||
// B *C
|
||||
// C A
|
||||
// )
|
||||
//
|
||||
// The type of C is the (named) type of A which is incomplete,
|
||||
// and which has as its underlying type the named type B.
|
||||
// Determine the (final, unnamed) underlying type by resolving
|
||||
// any forward chain (they always end in an unnamed type).
|
||||
named.underlying = underlying(named.underlying)
|
||||
|
||||
}
|
||||
|
||||
// check and add associated methods
|
||||
// TODO(gri) It's easy to create pathological cases where the
|
||||
// current approach is incorrect: In general we need to know
|
||||
// and add all methods _before_ type-checking the type.
|
||||
// See https://play.golang.org/p/WMpE0q2wK8
|
||||
check.addMethodDecls(obj)
|
||||
}
|
||||
|
||||
func (check *Checker) addMethodDecls(obj *TypeName) {
|
||||
// get associated methods
|
||||
methods := check.methods[obj.name]
|
||||
if len(methods) == 0 {
|
||||
return // no methods
|
||||
}
|
||||
delete(check.methods, obj.name)
|
||||
|
||||
// use an objset to check for name conflicts
|
||||
var mset objset
|
||||
|
||||
// spec: "If the base type is a struct type, the non-blank method
|
||||
// and field names must be distinct."
|
||||
base, _ := obj.typ.(*Named) // nil if receiver base type is type alias
|
||||
if base != nil {
|
||||
if t, _ := base.underlying.(*Struct); t != nil {
|
||||
for _, fld := range t.fields {
|
||||
if fld.name != "_" {
|
||||
assert(mset.insert(fld) == nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Checker.Files may be called multiple times; additional package files
|
||||
// may add methods to already type-checked types. Add pre-existing methods
|
||||
// so that we can detect redeclarations.
|
||||
for _, m := range base.methods {
|
||||
assert(m.name != "_")
|
||||
assert(mset.insert(m) == nil)
|
||||
}
|
||||
}
|
||||
|
||||
// type-check methods
|
||||
for _, m := range methods {
|
||||
// spec: "For a base type, the non-blank names of methods bound
|
||||
// to it must be unique."
|
||||
if m.name != "_" {
|
||||
if alt := mset.insert(m); alt != nil {
|
||||
switch alt.(type) {
|
||||
case *Var:
|
||||
check.errorf(m.pos, "field and method with the same name %s", m.name)
|
||||
case *Func:
|
||||
check.errorf(m.pos, "method %s already declared for %s", m.name, obj)
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
check.reportAltDecl(alt)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// type-check
|
||||
check.objDecl(m, nil, nil)
|
||||
|
||||
// methods with blank _ names cannot be found - don't keep them
|
||||
if base != nil && m.name != "_" {
|
||||
base.methods = append(base.methods, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
|
||||
assert(obj.typ == nil)
|
||||
|
||||
// func declarations cannot use iota
|
||||
assert(check.iota == nil)
|
||||
|
||||
sig := new(Signature)
|
||||
obj.typ = sig // guard against cycles
|
||||
fdecl := decl.fdecl
|
||||
check.funcType(sig, fdecl.Recv, fdecl.Type)
|
||||
if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) {
|
||||
check.errorf(fdecl.Pos(), "func init must have no arguments and no return values")
|
||||
// ok to continue
|
||||
}
|
||||
|
||||
// function body must be type-checked after global declarations
|
||||
// (functions implemented elsewhere have no body)
|
||||
if !check.conf.IgnoreFuncBodies && fdecl.Body != nil {
|
||||
check.later(obj.name, decl, sig, fdecl.Body)
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) declStmt(decl ast.Decl) {
|
||||
pkg := check.pkg
|
||||
|
||||
switch d := decl.(type) {
|
||||
case *ast.BadDecl:
|
||||
// ignore
|
||||
|
||||
case *ast.GenDecl:
|
||||
var last *ast.ValueSpec // last ValueSpec with type or init exprs seen
|
||||
for iota, spec := range d.Specs {
|
||||
switch s := spec.(type) {
|
||||
case *ast.ValueSpec:
|
||||
switch d.Tok {
|
||||
case token.CONST:
|
||||
// determine which init exprs to use
|
||||
switch {
|
||||
case s.Type != nil || len(s.Values) > 0:
|
||||
last = s
|
||||
case last == nil:
|
||||
last = new(ast.ValueSpec) // make sure last exists
|
||||
}
|
||||
|
||||
// declare all constants
|
||||
lhs := make([]*Const, len(s.Names))
|
||||
for i, name := range s.Names {
|
||||
obj := NewConst(name.Pos(), pkg, name.Name, nil, constant.MakeInt64(int64(iota)))
|
||||
lhs[i] = obj
|
||||
|
||||
var init ast.Expr
|
||||
if i < len(last.Values) {
|
||||
init = last.Values[i]
|
||||
}
|
||||
|
||||
check.constDecl(obj, last.Type, init)
|
||||
}
|
||||
|
||||
check.arityMatch(s, last)
|
||||
|
||||
// spec: "The scope of a constant or variable identifier declared
|
||||
// inside a function begins at the end of the ConstSpec or VarSpec
|
||||
// (ShortVarDecl for short variable declarations) and ends at the
|
||||
// end of the innermost containing block."
|
||||
scopePos := s.End()
|
||||
for i, name := range s.Names {
|
||||
check.declare(check.scope, name, lhs[i], scopePos)
|
||||
}
|
||||
|
||||
case token.VAR:
|
||||
lhs0 := make([]*Var, len(s.Names))
|
||||
for i, name := range s.Names {
|
||||
lhs0[i] = NewVar(name.Pos(), pkg, name.Name, nil)
|
||||
}
|
||||
|
||||
// initialize all variables
|
||||
for i, obj := range lhs0 {
|
||||
var lhs []*Var
|
||||
var init ast.Expr
|
||||
switch len(s.Values) {
|
||||
case len(s.Names):
|
||||
// lhs and rhs match
|
||||
init = s.Values[i]
|
||||
case 1:
|
||||
// rhs is expected to be a multi-valued expression
|
||||
lhs = lhs0
|
||||
init = s.Values[0]
|
||||
default:
|
||||
if i < len(s.Values) {
|
||||
init = s.Values[i]
|
||||
}
|
||||
}
|
||||
check.varDecl(obj, lhs, s.Type, init)
|
||||
if len(s.Values) == 1 {
|
||||
// If we have a single lhs variable we are done either way.
|
||||
// If we have a single rhs expression, it must be a multi-
|
||||
// valued expression, in which case handling the first lhs
|
||||
// variable will cause all lhs variables to have a type
|
||||
// assigned, and we are done as well.
|
||||
if debug {
|
||||
for _, obj := range lhs0 {
|
||||
assert(obj.typ != nil)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
check.arityMatch(s, nil)
|
||||
|
||||
// declare all variables
|
||||
// (only at this point are the variable scopes (parents) set)
|
||||
scopePos := s.End() // see constant declarations
|
||||
for i, name := range s.Names {
|
||||
// see constant declarations
|
||||
check.declare(check.scope, name, lhs0[i], scopePos)
|
||||
}
|
||||
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "invalid token %s", d.Tok)
|
||||
}
|
||||
|
||||
case *ast.TypeSpec:
|
||||
obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil)
|
||||
// spec: "The scope of a type identifier declared inside a function
|
||||
// begins at the identifier in the TypeSpec and ends at the end of
|
||||
// the innermost containing block."
|
||||
scopePos := s.Name.Pos()
|
||||
check.declare(check.scope, s.Name, obj, scopePos)
|
||||
check.typeDecl(obj, s.Type, nil, nil, s.Assign.IsValid())
|
||||
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "const, type, or var declaration expected")
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
|
||||
}
|
||||
}
|
103
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/errors.go
generated
vendored
103
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/errors.go
generated
vendored
@ -1,103 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements various error reporters.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func assert(p bool) {
|
||||
if !p {
|
||||
panic("assertion failed")
|
||||
}
|
||||
}
|
||||
|
||||
func unreachable() {
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (check *Checker) qualifier(pkg *Package) string {
|
||||
if pkg != check.pkg {
|
||||
return pkg.path
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (check *Checker) sprintf(format string, args ...interface{}) string {
|
||||
for i, arg := range args {
|
||||
switch a := arg.(type) {
|
||||
case nil:
|
||||
arg = "<nil>"
|
||||
case operand:
|
||||
panic("internal error: should always pass *operand")
|
||||
case *operand:
|
||||
arg = operandString(a, check.qualifier)
|
||||
case token.Pos:
|
||||
arg = check.fset.Position(a).String()
|
||||
case ast.Expr:
|
||||
arg = ExprString(a)
|
||||
case Object:
|
||||
arg = ObjectString(a, check.qualifier)
|
||||
case Type:
|
||||
arg = TypeString(a, check.qualifier)
|
||||
}
|
||||
args[i] = arg
|
||||
}
|
||||
return fmt.Sprintf(format, args...)
|
||||
}
|
||||
|
||||
func (check *Checker) trace(pos token.Pos, format string, args ...interface{}) {
|
||||
fmt.Printf("%s:\t%s%s\n",
|
||||
check.fset.Position(pos),
|
||||
strings.Repeat(". ", check.indent),
|
||||
check.sprintf(format, args...),
|
||||
)
|
||||
}
|
||||
|
||||
// dump is only needed for debugging
|
||||
func (check *Checker) dump(format string, args ...interface{}) {
|
||||
fmt.Println(check.sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (check *Checker) err(pos token.Pos, msg string, soft bool) {
|
||||
err := Error{check.fset, pos, msg, soft}
|
||||
if check.firstErr == nil {
|
||||
check.firstErr = err
|
||||
}
|
||||
f := check.conf.Error
|
||||
if f == nil {
|
||||
panic(bailout{}) // report only first error
|
||||
}
|
||||
f(err)
|
||||
}
|
||||
|
||||
func (check *Checker) error(pos token.Pos, msg string) {
|
||||
check.err(pos, msg, false)
|
||||
}
|
||||
|
||||
func (check *Checker) errorf(pos token.Pos, format string, args ...interface{}) {
|
||||
check.err(pos, check.sprintf(format, args...), false)
|
||||
}
|
||||
|
||||
func (check *Checker) softErrorf(pos token.Pos, format string, args ...interface{}) {
|
||||
check.err(pos, check.sprintf(format, args...), true)
|
||||
}
|
||||
|
||||
func (check *Checker) invalidAST(pos token.Pos, format string, args ...interface{}) {
|
||||
check.errorf(pos, "invalid AST: "+format, args...)
|
||||
}
|
||||
|
||||
func (check *Checker) invalidArg(pos token.Pos, format string, args ...interface{}) {
|
||||
check.errorf(pos, "invalid argument: "+format, args...)
|
||||
}
|
||||
|
||||
func (check *Checker) invalidOp(pos token.Pos, format string, args ...interface{}) {
|
||||
check.errorf(pos, "invalid operation: "+format, args...)
|
||||
}
|
83
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/eval.go
generated
vendored
83
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/eval.go
generated
vendored
@ -1,83 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// Eval returns the type and, if constant, the value for the
|
||||
// expression expr, evaluated at position pos of package pkg,
|
||||
// which must have been derived from type-checking an AST with
|
||||
// complete position information relative to the provided file
|
||||
// set.
|
||||
//
|
||||
// If the expression contains function literals, their bodies
|
||||
// are ignored (i.e., the bodies are not type-checked).
|
||||
//
|
||||
// If pkg == nil, the Universe scope is used and the provided
|
||||
// position pos is ignored. If pkg != nil, and pos is invalid,
|
||||
// the package scope is used. Otherwise, pos must belong to the
|
||||
// package.
|
||||
//
|
||||
// An error is returned if pos is not within the package or
|
||||
// if the node cannot be evaluated.
|
||||
//
|
||||
// Note: Eval should not be used instead of running Check to compute
|
||||
// types and values, but in addition to Check. Eval will re-evaluate
|
||||
// its argument each time, and it also does not know about the context
|
||||
// in which an expression is used (e.g., an assignment). Thus, top-
|
||||
// level untyped constants will return an untyped type rather then the
|
||||
// respective context-specific type.
|
||||
//
|
||||
func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (TypeAndValue, error) {
|
||||
// determine scope
|
||||
var scope *Scope
|
||||
if pkg == nil {
|
||||
scope = Universe
|
||||
pos = token.NoPos
|
||||
} else if !pos.IsValid() {
|
||||
scope = pkg.scope
|
||||
} else {
|
||||
// The package scope extent (position information) may be
|
||||
// incorrect (files spread across a wide range of fset
|
||||
// positions) - ignore it and just consider its children
|
||||
// (file scopes).
|
||||
for _, fscope := range pkg.scope.children {
|
||||
if scope = fscope.Innermost(pos); scope != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if scope == nil || debug {
|
||||
s := scope
|
||||
for s != nil && s != pkg.scope {
|
||||
s = s.parent
|
||||
}
|
||||
// s == nil || s == pkg.scope
|
||||
if s == nil {
|
||||
return TypeAndValue{}, fmt.Errorf("no position %s found in package %s", fset.Position(pos), pkg.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse expressions
|
||||
node, err := parser.ParseExprFrom(fset, "eval", expr, 0)
|
||||
if err != nil {
|
||||
return TypeAndValue{}, err
|
||||
}
|
||||
|
||||
// initialize checker
|
||||
check := NewChecker(nil, fset, pkg, nil)
|
||||
check.scope = scope
|
||||
check.pos = pos
|
||||
defer check.handleBailout(&err)
|
||||
|
||||
// evaluate node
|
||||
var x operand
|
||||
check.rawExpr(&x, node, nil)
|
||||
return TypeAndValue{x.mode, x.typ, x.val}, err
|
||||
}
|
1623
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/expr.go
generated
vendored
1623
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/expr.go
generated
vendored
File diff suppressed because it is too large
Load Diff
224
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/exprstring.go
generated
vendored
224
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/exprstring.go
generated
vendored
@ -1,224 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements printing of expressions.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/ast"
|
||||
)
|
||||
|
||||
// ExprString returns the (possibly shortened) string representation for x.
|
||||
// Shortened representations are suitable for user interfaces but may not
|
||||
// necessarily follow Go syntax.
|
||||
func ExprString(x ast.Expr) string {
|
||||
var buf bytes.Buffer
|
||||
WriteExpr(&buf, x)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// WriteExpr writes the (possibly shortened) string representation for x to buf.
|
||||
// Shortened representations are suitable for user interfaces but may not
|
||||
// necessarily follow Go syntax.
|
||||
func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
|
||||
// The AST preserves source-level parentheses so there is
|
||||
// no need to introduce them here to correct for different
|
||||
// operator precedences. (This assumes that the AST was
|
||||
// generated by a Go parser.)
|
||||
|
||||
switch x := x.(type) {
|
||||
default:
|
||||
buf.WriteString("(bad expr)") // nil, ast.BadExpr, ast.KeyValueExpr
|
||||
|
||||
case *ast.Ident:
|
||||
buf.WriteString(x.Name)
|
||||
|
||||
case *ast.Ellipsis:
|
||||
buf.WriteString("...")
|
||||
if x.Elt != nil {
|
||||
WriteExpr(buf, x.Elt)
|
||||
}
|
||||
|
||||
case *ast.BasicLit:
|
||||
buf.WriteString(x.Value)
|
||||
|
||||
case *ast.FuncLit:
|
||||
buf.WriteByte('(')
|
||||
WriteExpr(buf, x.Type)
|
||||
buf.WriteString(" literal)") // shortened
|
||||
|
||||
case *ast.CompositeLit:
|
||||
buf.WriteByte('(')
|
||||
WriteExpr(buf, x.Type)
|
||||
buf.WriteString(" literal)") // shortened
|
||||
|
||||
case *ast.ParenExpr:
|
||||
buf.WriteByte('(')
|
||||
WriteExpr(buf, x.X)
|
||||
buf.WriteByte(')')
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
WriteExpr(buf, x.X)
|
||||
buf.WriteByte('.')
|
||||
buf.WriteString(x.Sel.Name)
|
||||
|
||||
case *ast.IndexExpr:
|
||||
WriteExpr(buf, x.X)
|
||||
buf.WriteByte('[')
|
||||
WriteExpr(buf, x.Index)
|
||||
buf.WriteByte(']')
|
||||
|
||||
case *ast.SliceExpr:
|
||||
WriteExpr(buf, x.X)
|
||||
buf.WriteByte('[')
|
||||
if x.Low != nil {
|
||||
WriteExpr(buf, x.Low)
|
||||
}
|
||||
buf.WriteByte(':')
|
||||
if x.High != nil {
|
||||
WriteExpr(buf, x.High)
|
||||
}
|
||||
if x.Slice3 {
|
||||
buf.WriteByte(':')
|
||||
if x.Max != nil {
|
||||
WriteExpr(buf, x.Max)
|
||||
}
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
|
||||
case *ast.TypeAssertExpr:
|
||||
WriteExpr(buf, x.X)
|
||||
buf.WriteString(".(")
|
||||
WriteExpr(buf, x.Type)
|
||||
buf.WriteByte(')')
|
||||
|
||||
case *ast.CallExpr:
|
||||
WriteExpr(buf, x.Fun)
|
||||
buf.WriteByte('(')
|
||||
for i, arg := range x.Args {
|
||||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
WriteExpr(buf, arg)
|
||||
}
|
||||
if x.Ellipsis.IsValid() {
|
||||
buf.WriteString("...")
|
||||
}
|
||||
buf.WriteByte(')')
|
||||
|
||||
case *ast.StarExpr:
|
||||
buf.WriteByte('*')
|
||||
WriteExpr(buf, x.X)
|
||||
|
||||
case *ast.UnaryExpr:
|
||||
buf.WriteString(x.Op.String())
|
||||
WriteExpr(buf, x.X)
|
||||
|
||||
case *ast.BinaryExpr:
|
||||
WriteExpr(buf, x.X)
|
||||
buf.WriteByte(' ')
|
||||
buf.WriteString(x.Op.String())
|
||||
buf.WriteByte(' ')
|
||||
WriteExpr(buf, x.Y)
|
||||
|
||||
case *ast.ArrayType:
|
||||
buf.WriteByte('[')
|
||||
if x.Len != nil {
|
||||
WriteExpr(buf, x.Len)
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
WriteExpr(buf, x.Elt)
|
||||
|
||||
case *ast.StructType:
|
||||
buf.WriteString("struct{")
|
||||
writeFieldList(buf, x.Fields, "; ", false)
|
||||
buf.WriteByte('}')
|
||||
|
||||
case *ast.FuncType:
|
||||
buf.WriteString("func")
|
||||
writeSigExpr(buf, x)
|
||||
|
||||
case *ast.InterfaceType:
|
||||
buf.WriteString("interface{")
|
||||
writeFieldList(buf, x.Methods, "; ", true)
|
||||
buf.WriteByte('}')
|
||||
|
||||
case *ast.MapType:
|
||||
buf.WriteString("map[")
|
||||
WriteExpr(buf, x.Key)
|
||||
buf.WriteByte(']')
|
||||
WriteExpr(buf, x.Value)
|
||||
|
||||
case *ast.ChanType:
|
||||
var s string
|
||||
switch x.Dir {
|
||||
case ast.SEND:
|
||||
s = "chan<- "
|
||||
case ast.RECV:
|
||||
s = "<-chan "
|
||||
default:
|
||||
s = "chan "
|
||||
}
|
||||
buf.WriteString(s)
|
||||
WriteExpr(buf, x.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) {
|
||||
buf.WriteByte('(')
|
||||
writeFieldList(buf, sig.Params, ", ", false)
|
||||
buf.WriteByte(')')
|
||||
|
||||
res := sig.Results
|
||||
n := res.NumFields()
|
||||
if n == 0 {
|
||||
// no result
|
||||
return
|
||||
}
|
||||
|
||||
buf.WriteByte(' ')
|
||||
if n == 1 && len(res.List[0].Names) == 0 {
|
||||
// single unnamed result
|
||||
WriteExpr(buf, res.List[0].Type)
|
||||
return
|
||||
}
|
||||
|
||||
// multiple or named result(s)
|
||||
buf.WriteByte('(')
|
||||
writeFieldList(buf, res, ", ", false)
|
||||
buf.WriteByte(')')
|
||||
}
|
||||
|
||||
func writeFieldList(buf *bytes.Buffer, fields *ast.FieldList, sep string, iface bool) {
|
||||
for i, f := range fields.List {
|
||||
if i > 0 {
|
||||
buf.WriteString(sep)
|
||||
}
|
||||
|
||||
// field list names
|
||||
for i, name := range f.Names {
|
||||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
buf.WriteString(name.Name)
|
||||
}
|
||||
|
||||
// types of interface methods consist of signatures only
|
||||
if sig, _ := f.Type.(*ast.FuncType); sig != nil && iface {
|
||||
writeSigExpr(buf, sig)
|
||||
continue
|
||||
}
|
||||
|
||||
// named fields are separated with a blank from the field type
|
||||
if len(f.Names) > 0 {
|
||||
buf.WriteByte(' ')
|
||||
}
|
||||
|
||||
WriteExpr(buf, f.Type)
|
||||
|
||||
// ignore tag
|
||||
}
|
||||
}
|
332
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/gotype.go
generated
vendored
332
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/gotype.go
generated
vendored
@ -1,332 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Build this command explicitly: go build gotype.go
|
||||
|
||||
/*
|
||||
The gotype command, like the front-end of a Go compiler, parses and
|
||||
type-checks a single Go package. Errors are reported if the analysis
|
||||
fails; otherwise gotype is quiet (unless -v is set).
|
||||
|
||||
Without a list of paths, gotype reads from standard input, which
|
||||
must provide a single Go source file defining a complete package.
|
||||
|
||||
With a single directory argument, gotype checks the Go files in
|
||||
that directory, comprising a single package. Use -t to include the
|
||||
(in-package) _test.go files. Use -x to type check only external
|
||||
test files.
|
||||
|
||||
Otherwise, each path must be the filename of a Go file belonging
|
||||
to the same package.
|
||||
|
||||
Imports are processed by importing directly from the source of
|
||||
imported packages (default), or by importing from compiled and
|
||||
installed packages (by setting -c to the respective compiler).
|
||||
|
||||
The -c flag must be set to a compiler ("gc", "gccgo") when type-
|
||||
checking packages containing imports with relative import paths
|
||||
(import "./mypkg") because the source importer cannot know which
|
||||
files to include for such packages.
|
||||
|
||||
Usage:
|
||||
gotype [flags] [path...]
|
||||
|
||||
The flags are:
|
||||
-t
|
||||
include local test files in a directory (ignored if -x is provided)
|
||||
-x
|
||||
consider only external test files in a directory
|
||||
-e
|
||||
report all errors (not just the first 10)
|
||||
-v
|
||||
verbose mode
|
||||
-c
|
||||
compiler used for installed packages (gc, gccgo, or source); default: source
|
||||
|
||||
Flags controlling additional output:
|
||||
-ast
|
||||
print AST (forces -seq)
|
||||
-trace
|
||||
print parse trace (forces -seq)
|
||||
-comments
|
||||
parse comments (ignored unless -ast or -trace is provided)
|
||||
|
||||
Examples:
|
||||
|
||||
To check the files a.go, b.go, and c.go:
|
||||
|
||||
gotype a.go b.go c.go
|
||||
|
||||
To check an entire package including (in-package) tests in the directory dir and print the processed files:
|
||||
|
||||
gotype -t -v dir
|
||||
|
||||
To check the external test package (if any) in the current directory, based on installed packages compiled with
|
||||
cmd/compile:
|
||||
|
||||
gotype -c=gc -x .
|
||||
|
||||
To verify the output of a pipe:
|
||||
|
||||
echo "package foo" | gotype
|
||||
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/importer"
|
||||
"go/parser"
|
||||
"go/scanner"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// main operation modes
|
||||
testFiles = flag.Bool("t", false, "include in-package test files in a directory")
|
||||
xtestFiles = flag.Bool("x", false, "consider only external test files in a directory")
|
||||
allErrors = flag.Bool("e", false, "report all errors, not just the first 10")
|
||||
verbose = flag.Bool("v", false, "verbose mode")
|
||||
compiler = flag.String("c", "source", "compiler used for installed packages (gc, gccgo, or source)")
|
||||
|
||||
// additional output control
|
||||
printAST = flag.Bool("ast", false, "print AST (forces -seq)")
|
||||
printTrace = flag.Bool("trace", false, "print parse trace (forces -seq)")
|
||||
parseComments = flag.Bool("comments", false, "parse comments (ignored unless -ast or -trace is provided)")
|
||||
)
|
||||
|
||||
var (
|
||||
fset = token.NewFileSet()
|
||||
errorCount = 0
|
||||
sequential = false
|
||||
parserMode parser.Mode
|
||||
)
|
||||
|
||||
func initParserMode() {
|
||||
if *allErrors {
|
||||
parserMode |= parser.AllErrors
|
||||
}
|
||||
if *printAST {
|
||||
sequential = true
|
||||
}
|
||||
if *printTrace {
|
||||
parserMode |= parser.Trace
|
||||
sequential = true
|
||||
}
|
||||
if *parseComments && (*printAST || *printTrace) {
|
||||
parserMode |= parser.ParseComments
|
||||
}
|
||||
}
|
||||
|
||||
const usageString = `usage: gotype [flags] [path ...]
|
||||
|
||||
The gotype command, like the front-end of a Go compiler, parses and
|
||||
type-checks a single Go package. Errors are reported if the analysis
|
||||
fails; otherwise gotype is quiet (unless -v is set).
|
||||
|
||||
Without a list of paths, gotype reads from standard input, which
|
||||
must provide a single Go source file defining a complete package.
|
||||
|
||||
With a single directory argument, gotype checks the Go files in
|
||||
that directory, comprising a single package. Use -t to include the
|
||||
(in-package) _test.go files. Use -x to type check only external
|
||||
test files.
|
||||
|
||||
Otherwise, each path must be the filename of a Go file belonging
|
||||
to the same package.
|
||||
|
||||
Imports are processed by importing directly from the source of
|
||||
imported packages (default), or by importing from compiled and
|
||||
installed packages (by setting -c to the respective compiler).
|
||||
|
||||
The -c flag must be set to a compiler ("gc", "gccgo") when type-
|
||||
checking packages containing imports with relative import paths
|
||||
(import "./mypkg") because the source importer cannot know which
|
||||
files to include for such packages.
|
||||
`
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintln(os.Stderr, usageString)
|
||||
flag.PrintDefaults()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func report(err error) {
|
||||
scanner.PrintError(os.Stderr, err)
|
||||
if list, ok := err.(scanner.ErrorList); ok {
|
||||
errorCount += len(list)
|
||||
return
|
||||
}
|
||||
errorCount++
|
||||
}
|
||||
|
||||
// parse may be called concurrently
|
||||
func parse(filename string, src interface{}) (*ast.File, error) {
|
||||
if *verbose {
|
||||
fmt.Println(filename)
|
||||
}
|
||||
file, err := parser.ParseFile(fset, filename, src, parserMode) // ok to access fset concurrently
|
||||
if *printAST {
|
||||
ast.Print(fset, file)
|
||||
}
|
||||
return file, err
|
||||
}
|
||||
|
||||
func parseStdin() (*ast.File, error) {
|
||||
src, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parse("<standard input>", src)
|
||||
}
|
||||
|
||||
func parseFiles(dir string, filenames []string) ([]*ast.File, error) {
|
||||
files := make([]*ast.File, len(filenames))
|
||||
errors := make([]error, len(filenames))
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i, filename := range filenames {
|
||||
wg.Add(1)
|
||||
go func(i int, filepath string) {
|
||||
defer wg.Done()
|
||||
files[i], errors[i] = parse(filepath, nil)
|
||||
}(i, filepath.Join(dir, filename))
|
||||
if sequential {
|
||||
wg.Wait()
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
// if there are errors, return the first one for deterministic results
|
||||
for _, err := range errors {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func parseDir(dir string) ([]*ast.File, error) {
|
||||
ctxt := build.Default
|
||||
pkginfo, err := ctxt.ImportDir(dir, 0)
|
||||
if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if *xtestFiles {
|
||||
return parseFiles(dir, pkginfo.XTestGoFiles)
|
||||
}
|
||||
|
||||
filenames := append(pkginfo.GoFiles, pkginfo.CgoFiles...)
|
||||
if *testFiles {
|
||||
filenames = append(filenames, pkginfo.TestGoFiles...)
|
||||
}
|
||||
return parseFiles(dir, filenames)
|
||||
}
|
||||
|
||||
func getPkgFiles(args []string) ([]*ast.File, error) {
|
||||
if len(args) == 0 {
|
||||
// stdin
|
||||
file, err := parseStdin()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []*ast.File{file}, nil
|
||||
}
|
||||
|
||||
if len(args) == 1 {
|
||||
// possibly a directory
|
||||
path := args[0]
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if info.IsDir() {
|
||||
return parseDir(path)
|
||||
}
|
||||
}
|
||||
|
||||
// list of files
|
||||
return parseFiles("", args)
|
||||
}
|
||||
|
||||
func checkPkgFiles(files []*ast.File) {
|
||||
type bailout struct{}
|
||||
|
||||
// if checkPkgFiles is called multiple times, set up conf only once
|
||||
conf := types.Config{
|
||||
FakeImportC: true,
|
||||
Error: func(err error) {
|
||||
if !*allErrors && errorCount >= 10 {
|
||||
panic(bailout{})
|
||||
}
|
||||
report(err)
|
||||
},
|
||||
Importer: importer.For(*compiler, nil),
|
||||
Sizes: types.SizesFor(build.Default.Compiler, build.Default.GOARCH),
|
||||
}
|
||||
|
||||
defer func() {
|
||||
switch p := recover().(type) {
|
||||
case nil, bailout:
|
||||
// normal return or early exit
|
||||
default:
|
||||
// re-panic
|
||||
panic(p)
|
||||
}
|
||||
}()
|
||||
|
||||
const path = "pkg" // any non-empty string will do for now
|
||||
conf.Check(path, fset, files, nil)
|
||||
}
|
||||
|
||||
func printStats(d time.Duration) {
|
||||
fileCount := 0
|
||||
lineCount := 0
|
||||
fset.Iterate(func(f *token.File) bool {
|
||||
fileCount++
|
||||
lineCount += f.LineCount()
|
||||
return true
|
||||
})
|
||||
|
||||
fmt.Printf(
|
||||
"%s (%d files, %d lines, %d lines/s)\n",
|
||||
d, fileCount, lineCount, int64(float64(lineCount)/d.Seconds()),
|
||||
)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
initParserMode()
|
||||
|
||||
start := time.Now()
|
||||
|
||||
files, err := getPkgFiles(flag.Args())
|
||||
if err != nil {
|
||||
report(err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
checkPkgFiles(files)
|
||||
if errorCount > 0 {
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if *verbose {
|
||||
printStats(time.Since(start))
|
||||
}
|
||||
}
|
297
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/initorder.go
generated
vendored
297
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/initorder.go
generated
vendored
@ -1,297 +0,0 @@
|
||||
// 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 types
|
||||
|
||||
import (
|
||||
"container/heap"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// initOrder computes the Info.InitOrder for package variables.
|
||||
func (check *Checker) initOrder() {
|
||||
// An InitOrder may already have been computed if a package is
|
||||
// built from several calls to (*Checker).Files. Clear it.
|
||||
check.Info.InitOrder = check.Info.InitOrder[:0]
|
||||
|
||||
// Compute the object dependency graph and initialize
|
||||
// a priority queue with the list of graph nodes.
|
||||
pq := nodeQueue(dependencyGraph(check.objMap))
|
||||
heap.Init(&pq)
|
||||
|
||||
const debug = false
|
||||
if debug {
|
||||
fmt.Printf("Computing initialization order for %s\n\n", check.pkg)
|
||||
fmt.Println("Object dependency graph:")
|
||||
for obj, d := range check.objMap {
|
||||
// only print objects that may appear in the dependency graph
|
||||
if obj, _ := obj.(dependency); obj != nil {
|
||||
if len(d.deps) > 0 {
|
||||
fmt.Printf("\t%s depends on\n", obj.Name())
|
||||
for dep := range d.deps {
|
||||
fmt.Printf("\t\t%s\n", dep.Name())
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("\t%s has no dependencies\n", obj.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
fmt.Println("Transposed object dependency graph (functions eliminated):")
|
||||
for _, n := range pq {
|
||||
fmt.Printf("\t%s depends on %d nodes\n", n.obj.Name(), n.ndeps)
|
||||
for p := range n.pred {
|
||||
fmt.Printf("\t\t%s is dependent\n", p.obj.Name())
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
fmt.Println("Processing nodes:")
|
||||
}
|
||||
|
||||
// Determine initialization order by removing the highest priority node
|
||||
// (the one with the fewest dependencies) and its edges from the graph,
|
||||
// repeatedly, until there are no nodes left.
|
||||
// In a valid Go program, those nodes always have zero dependencies (after
|
||||
// removing all incoming dependencies), otherwise there are initialization
|
||||
// cycles.
|
||||
emitted := make(map[*declInfo]bool)
|
||||
for len(pq) > 0 {
|
||||
// get the next node
|
||||
n := heap.Pop(&pq).(*graphNode)
|
||||
|
||||
if debug {
|
||||
fmt.Printf("\t%s (src pos %d) depends on %d nodes now\n",
|
||||
n.obj.Name(), n.obj.order(), n.ndeps)
|
||||
}
|
||||
|
||||
// if n still depends on other nodes, we have a cycle
|
||||
if n.ndeps > 0 {
|
||||
cycle := findPath(check.objMap, n.obj, n.obj, make(objSet))
|
||||
// If n.obj is not part of the cycle (e.g., n.obj->b->c->d->c),
|
||||
// cycle will be nil. Don't report anything in that case since
|
||||
// the cycle is reported when the algorithm gets to an object
|
||||
// in the cycle.
|
||||
// Furthermore, once an object in the cycle is encountered,
|
||||
// the cycle will be broken (dependency count will be reduced
|
||||
// below), and so the remaining nodes in the cycle don't trigger
|
||||
// another error (unless they are part of multiple cycles).
|
||||
if cycle != nil {
|
||||
check.reportCycle(cycle)
|
||||
}
|
||||
// Ok to continue, but the variable initialization order
|
||||
// will be incorrect at this point since it assumes no
|
||||
// cycle errors.
|
||||
}
|
||||
|
||||
// reduce dependency count of all dependent nodes
|
||||
// and update priority queue
|
||||
for p := range n.pred {
|
||||
p.ndeps--
|
||||
heap.Fix(&pq, p.index)
|
||||
}
|
||||
|
||||
// record the init order for variables with initializers only
|
||||
v, _ := n.obj.(*Var)
|
||||
info := check.objMap[v]
|
||||
if v == nil || !info.hasInitializer() {
|
||||
continue
|
||||
}
|
||||
|
||||
// n:1 variable declarations such as: a, b = f()
|
||||
// introduce a node for each lhs variable (here: a, b);
|
||||
// but they all have the same initializer - emit only
|
||||
// one, for the first variable seen
|
||||
if emitted[info] {
|
||||
continue // initializer already emitted, if any
|
||||
}
|
||||
emitted[info] = true
|
||||
|
||||
infoLhs := info.lhs // possibly nil (see declInfo.lhs field comment)
|
||||
if infoLhs == nil {
|
||||
infoLhs = []*Var{v}
|
||||
}
|
||||
init := &Initializer{infoLhs, info.init}
|
||||
check.Info.InitOrder = append(check.Info.InitOrder, init)
|
||||
}
|
||||
|
||||
if debug {
|
||||
fmt.Println()
|
||||
fmt.Println("Initialization order:")
|
||||
for _, init := range check.Info.InitOrder {
|
||||
fmt.Printf("\t%s\n", init)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
// findPath returns the (reversed) list of objects []Object{to, ... from}
|
||||
// such that there is a path of object dependencies from 'from' to 'to'.
|
||||
// If there is no such path, the result is nil.
|
||||
func findPath(objMap map[Object]*declInfo, from, to Object, visited objSet) []Object {
|
||||
if visited[from] {
|
||||
return nil // node already seen
|
||||
}
|
||||
visited[from] = true
|
||||
|
||||
for d := range objMap[from].deps {
|
||||
if d == to {
|
||||
return []Object{d}
|
||||
}
|
||||
if P := findPath(objMap, d, to, visited); P != nil {
|
||||
return append(P, d)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// reportCycle reports an error for the given cycle.
|
||||
func (check *Checker) reportCycle(cycle []Object) {
|
||||
obj := cycle[0]
|
||||
check.errorf(obj.Pos(), "initialization cycle for %s", obj.Name())
|
||||
// subtle loop: print cycle[i] for i = 0, n-1, n-2, ... 1 for len(cycle) = n
|
||||
for i := len(cycle) - 1; i >= 0; i-- {
|
||||
check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
|
||||
obj = cycle[i]
|
||||
}
|
||||
// print cycle[0] again to close the cycle
|
||||
check.errorf(obj.Pos(), "\t%s", obj.Name())
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Object dependency graph
|
||||
|
||||
// A dependency is an object that may be a dependency in an initialization
|
||||
// expression. Only constants, variables, and functions can be dependencies.
|
||||
// Constants are here because constant expression cycles are reported during
|
||||
// initialization order computation.
|
||||
type dependency interface {
|
||||
Object
|
||||
isDependency()
|
||||
}
|
||||
|
||||
// A graphNode represents a node in the object dependency graph.
|
||||
// Each node p in n.pred represents an edge p->n, and each node
|
||||
// s in n.succ represents an edge n->s; with a->b indicating that
|
||||
// a depends on b.
|
||||
type graphNode struct {
|
||||
obj dependency // object represented by this node
|
||||
pred, succ nodeSet // consumers and dependencies of this node (lazily initialized)
|
||||
index int // node index in graph slice/priority queue
|
||||
ndeps int // number of outstanding dependencies before this object can be initialized
|
||||
}
|
||||
|
||||
type nodeSet map[*graphNode]bool
|
||||
|
||||
func (s *nodeSet) add(p *graphNode) {
|
||||
if *s == nil {
|
||||
*s = make(nodeSet)
|
||||
}
|
||||
(*s)[p] = true
|
||||
}
|
||||
|
||||
// dependencyGraph computes the object dependency graph from the given objMap,
|
||||
// with any function nodes removed. The resulting graph contains only constants
|
||||
// and variables.
|
||||
func dependencyGraph(objMap map[Object]*declInfo) []*graphNode {
|
||||
// M is the dependency (Object) -> graphNode mapping
|
||||
M := make(map[dependency]*graphNode)
|
||||
for obj := range objMap {
|
||||
// only consider nodes that may be an initialization dependency
|
||||
if obj, _ := obj.(dependency); obj != nil {
|
||||
M[obj] = &graphNode{obj: obj}
|
||||
}
|
||||
}
|
||||
|
||||
// compute edges for graph M
|
||||
// (We need to include all nodes, even isolated ones, because they still need
|
||||
// to be scheduled for initialization in correct order relative to other nodes.)
|
||||
for obj, n := range M {
|
||||
// for each dependency obj -> d (= deps[i]), create graph edges n->s and s->n
|
||||
for d := range objMap[obj].deps {
|
||||
// only consider nodes that may be an initialization dependency
|
||||
if d, _ := d.(dependency); d != nil {
|
||||
d := M[d]
|
||||
n.succ.add(d)
|
||||
d.pred.add(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove function nodes and collect remaining graph nodes in G
|
||||
// (Mutually recursive functions may introduce cycles among themselves
|
||||
// which are permitted. Yet such cycles may incorrectly inflate the dependency
|
||||
// count for variables which in turn may not get scheduled for initialization
|
||||
// in correct order.)
|
||||
var G []*graphNode
|
||||
for obj, n := range M {
|
||||
if _, ok := obj.(*Func); ok {
|
||||
// connect each predecessor p of n with each successor s
|
||||
// and drop the function node (don't collect it in G)
|
||||
for p := range n.pred {
|
||||
// ignore self-cycles
|
||||
if p != n {
|
||||
// Each successor s of n becomes a successor of p, and
|
||||
// each predecessor p of n becomes a predecessor of s.
|
||||
for s := range n.succ {
|
||||
// ignore self-cycles
|
||||
if s != n {
|
||||
p.succ.add(s)
|
||||
s.pred.add(p)
|
||||
delete(s.pred, n) // remove edge to n
|
||||
}
|
||||
}
|
||||
delete(p.succ, n) // remove edge to n
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// collect non-function nodes
|
||||
G = append(G, n)
|
||||
}
|
||||
}
|
||||
|
||||
// fill in index and ndeps fields
|
||||
for i, n := range G {
|
||||
n.index = i
|
||||
n.ndeps = len(n.succ)
|
||||
}
|
||||
|
||||
return G
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Priority queue
|
||||
|
||||
// nodeQueue implements the container/heap interface;
|
||||
// a nodeQueue may be used as a priority queue.
|
||||
type nodeQueue []*graphNode
|
||||
|
||||
func (a nodeQueue) Len() int { return len(a) }
|
||||
|
||||
func (a nodeQueue) Swap(i, j int) {
|
||||
x, y := a[i], a[j]
|
||||
a[i], a[j] = y, x
|
||||
x.index, y.index = j, i
|
||||
}
|
||||
|
||||
func (a nodeQueue) Less(i, j int) bool {
|
||||
x, y := a[i], a[j]
|
||||
// nodes are prioritized by number of incoming dependencies (1st key)
|
||||
// and source order (2nd key)
|
||||
return x.ndeps < y.ndeps || x.ndeps == y.ndeps && x.obj.order() < y.obj.order()
|
||||
}
|
||||
|
||||
func (a *nodeQueue) Push(x interface{}) {
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (a *nodeQueue) Pop() interface{} {
|
||||
n := len(*a)
|
||||
x := (*a)[n-1]
|
||||
x.index = -1 // for safety
|
||||
*a = (*a)[:n-1]
|
||||
return x
|
||||
}
|
268
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/labels.go
generated
vendored
268
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/labels.go
generated
vendored
@ -1,268 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// labels checks correct label use in body.
|
||||
func (check *Checker) labels(body *ast.BlockStmt) {
|
||||
// set of all labels in this body
|
||||
all := NewScope(nil, body.Pos(), body.End(), "label")
|
||||
|
||||
fwdJumps := check.blockBranches(all, nil, nil, body.List)
|
||||
|
||||
// If there are any forward jumps left, no label was found for
|
||||
// the corresponding goto statements. Either those labels were
|
||||
// never defined, or they are inside blocks and not reachable
|
||||
// for the respective gotos.
|
||||
for _, jmp := range fwdJumps {
|
||||
var msg string
|
||||
name := jmp.Label.Name
|
||||
if alt := all.Lookup(name); alt != nil {
|
||||
msg = "goto %s jumps into block"
|
||||
alt.(*Label).used = true // avoid another error
|
||||
} else {
|
||||
msg = "label %s not declared"
|
||||
}
|
||||
check.errorf(jmp.Label.Pos(), msg, name)
|
||||
}
|
||||
|
||||
// spec: "It is illegal to define a label that is never used."
|
||||
for _, obj := range all.elems {
|
||||
if lbl := obj.(*Label); !lbl.used {
|
||||
check.softErrorf(lbl.pos, "label %s declared but not used", lbl.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A block tracks label declarations in a block and its enclosing blocks.
|
||||
type block struct {
|
||||
parent *block // enclosing block
|
||||
lstmt *ast.LabeledStmt // labeled statement to which this block belongs, or nil
|
||||
labels map[string]*ast.LabeledStmt // allocated lazily
|
||||
}
|
||||
|
||||
// insert records a new label declaration for the current block.
|
||||
// The label must not have been declared before in any block.
|
||||
func (b *block) insert(s *ast.LabeledStmt) {
|
||||
name := s.Label.Name
|
||||
if debug {
|
||||
assert(b.gotoTarget(name) == nil)
|
||||
}
|
||||
labels := b.labels
|
||||
if labels == nil {
|
||||
labels = make(map[string]*ast.LabeledStmt)
|
||||
b.labels = labels
|
||||
}
|
||||
labels[name] = s
|
||||
}
|
||||
|
||||
// gotoTarget returns the labeled statement in the current
|
||||
// or an enclosing block with the given label name, or nil.
|
||||
func (b *block) gotoTarget(name string) *ast.LabeledStmt {
|
||||
for s := b; s != nil; s = s.parent {
|
||||
if t := s.labels[name]; t != nil {
|
||||
return t
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// enclosingTarget returns the innermost enclosing labeled
|
||||
// statement with the given label name, or nil.
|
||||
func (b *block) enclosingTarget(name string) *ast.LabeledStmt {
|
||||
for s := b; s != nil; s = s.parent {
|
||||
if t := s.lstmt; t != nil && t.Label.Name == name {
|
||||
return t
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// blockBranches processes a block's statement list and returns the set of outgoing forward jumps.
|
||||
// all is the scope of all declared labels, parent the set of labels declared in the immediately
|
||||
// enclosing block, and lstmt is the labeled statement this block is associated with (or nil).
|
||||
func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.LabeledStmt, list []ast.Stmt) []*ast.BranchStmt {
|
||||
b := &block{parent: parent, lstmt: lstmt}
|
||||
|
||||
var (
|
||||
varDeclPos token.Pos
|
||||
fwdJumps, badJumps []*ast.BranchStmt
|
||||
)
|
||||
|
||||
// All forward jumps jumping over a variable declaration are possibly
|
||||
// invalid (they may still jump out of the block and be ok).
|
||||
// recordVarDecl records them for the given position.
|
||||
recordVarDecl := func(pos token.Pos) {
|
||||
varDeclPos = pos
|
||||
badJumps = append(badJumps[:0], fwdJumps...) // copy fwdJumps to badJumps
|
||||
}
|
||||
|
||||
jumpsOverVarDecl := func(jmp *ast.BranchStmt) bool {
|
||||
if varDeclPos.IsValid() {
|
||||
for _, bad := range badJumps {
|
||||
if jmp == bad {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
blockBranches := func(lstmt *ast.LabeledStmt, list []ast.Stmt) {
|
||||
// Unresolved forward jumps inside the nested block
|
||||
// become forward jumps in the current block.
|
||||
fwdJumps = append(fwdJumps, check.blockBranches(all, b, lstmt, list)...)
|
||||
}
|
||||
|
||||
var stmtBranches func(ast.Stmt)
|
||||
stmtBranches = func(s ast.Stmt) {
|
||||
switch s := s.(type) {
|
||||
case *ast.DeclStmt:
|
||||
if d, _ := s.Decl.(*ast.GenDecl); d != nil && d.Tok == token.VAR {
|
||||
recordVarDecl(d.Pos())
|
||||
}
|
||||
|
||||
case *ast.LabeledStmt:
|
||||
// declare non-blank label
|
||||
if name := s.Label.Name; name != "_" {
|
||||
lbl := NewLabel(s.Label.Pos(), check.pkg, name)
|
||||
if alt := all.Insert(lbl); alt != nil {
|
||||
check.softErrorf(lbl.pos, "label %s already declared", name)
|
||||
check.reportAltDecl(alt)
|
||||
// ok to continue
|
||||
} else {
|
||||
b.insert(s)
|
||||
check.recordDef(s.Label, lbl)
|
||||
}
|
||||
// resolve matching forward jumps and remove them from fwdJumps
|
||||
i := 0
|
||||
for _, jmp := range fwdJumps {
|
||||
if jmp.Label.Name == name {
|
||||
// match
|
||||
lbl.used = true
|
||||
check.recordUse(jmp.Label, lbl)
|
||||
if jumpsOverVarDecl(jmp) {
|
||||
check.softErrorf(
|
||||
jmp.Label.Pos(),
|
||||
"goto %s jumps over variable declaration at line %d",
|
||||
name,
|
||||
check.fset.Position(varDeclPos).Line,
|
||||
)
|
||||
// ok to continue
|
||||
}
|
||||
} else {
|
||||
// no match - record new forward jump
|
||||
fwdJumps[i] = jmp
|
||||
i++
|
||||
}
|
||||
}
|
||||
fwdJumps = fwdJumps[:i]
|
||||
lstmt = s
|
||||
}
|
||||
stmtBranches(s.Stmt)
|
||||
|
||||
case *ast.BranchStmt:
|
||||
if s.Label == nil {
|
||||
return // checked in 1st pass (check.stmt)
|
||||
}
|
||||
|
||||
// determine and validate target
|
||||
name := s.Label.Name
|
||||
switch s.Tok {
|
||||
case token.BREAK:
|
||||
// spec: "If there is a label, it must be that of an enclosing
|
||||
// "for", "switch", or "select" statement, and that is the one
|
||||
// whose execution terminates."
|
||||
valid := false
|
||||
if t := b.enclosingTarget(name); t != nil {
|
||||
switch t.Stmt.(type) {
|
||||
case *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt, *ast.ForStmt, *ast.RangeStmt:
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
if !valid {
|
||||
check.errorf(s.Label.Pos(), "invalid break label %s", name)
|
||||
return
|
||||
}
|
||||
|
||||
case token.CONTINUE:
|
||||
// spec: "If there is a label, it must be that of an enclosing
|
||||
// "for" statement, and that is the one whose execution advances."
|
||||
valid := false
|
||||
if t := b.enclosingTarget(name); t != nil {
|
||||
switch t.Stmt.(type) {
|
||||
case *ast.ForStmt, *ast.RangeStmt:
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
if !valid {
|
||||
check.errorf(s.Label.Pos(), "invalid continue label %s", name)
|
||||
return
|
||||
}
|
||||
|
||||
case token.GOTO:
|
||||
if b.gotoTarget(name) == nil {
|
||||
// label may be declared later - add branch to forward jumps
|
||||
fwdJumps = append(fwdJumps, s)
|
||||
return
|
||||
}
|
||||
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "branch statement: %s %s", s.Tok, name)
|
||||
return
|
||||
}
|
||||
|
||||
// record label use
|
||||
obj := all.Lookup(name)
|
||||
obj.(*Label).used = true
|
||||
check.recordUse(s.Label, obj)
|
||||
|
||||
case *ast.AssignStmt:
|
||||
if s.Tok == token.DEFINE {
|
||||
recordVarDecl(s.Pos())
|
||||
}
|
||||
|
||||
case *ast.BlockStmt:
|
||||
blockBranches(lstmt, s.List)
|
||||
|
||||
case *ast.IfStmt:
|
||||
stmtBranches(s.Body)
|
||||
if s.Else != nil {
|
||||
stmtBranches(s.Else)
|
||||
}
|
||||
|
||||
case *ast.CaseClause:
|
||||
blockBranches(nil, s.Body)
|
||||
|
||||
case *ast.SwitchStmt:
|
||||
stmtBranches(s.Body)
|
||||
|
||||
case *ast.TypeSwitchStmt:
|
||||
stmtBranches(s.Body)
|
||||
|
||||
case *ast.CommClause:
|
||||
blockBranches(nil, s.Body)
|
||||
|
||||
case *ast.SelectStmt:
|
||||
stmtBranches(s.Body)
|
||||
|
||||
case *ast.ForStmt:
|
||||
stmtBranches(s.Body)
|
||||
|
||||
case *ast.RangeStmt:
|
||||
stmtBranches(s.Body)
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range list {
|
||||
stmtBranches(s)
|
||||
}
|
||||
|
||||
return fwdJumps
|
||||
}
|
354
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/lookup.go
generated
vendored
354
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/lookup.go
generated
vendored
@ -1,354 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements various field and method lookup functions.
|
||||
|
||||
package types
|
||||
|
||||
// LookupFieldOrMethod looks up a field or method with given package and name
|
||||
// in T and returns the corresponding *Var or *Func, an index sequence, and a
|
||||
// bool indicating if there were any pointer indirections on the path to the
|
||||
// field or method. If addressable is set, T is the type of an addressable
|
||||
// variable (only matters for method lookups).
|
||||
//
|
||||
// The last index entry is the field or method index in the (possibly embedded)
|
||||
// type where the entry was found, either:
|
||||
//
|
||||
// 1) the list of declared methods of a named type; or
|
||||
// 2) the list of all methods (method set) of an interface type; or
|
||||
// 3) the list of fields of a struct type.
|
||||
//
|
||||
// The earlier index entries are the indices of the anonymous struct fields
|
||||
// traversed to get to the found entry, starting at depth 0.
|
||||
//
|
||||
// If no entry is found, a nil object is returned. In this case, the returned
|
||||
// index and indirect values have the following meaning:
|
||||
//
|
||||
// - If index != nil, the index sequence points to an ambiguous entry
|
||||
// (the same name appeared more than once at the same embedding level).
|
||||
//
|
||||
// - If indirect is set, a method with a pointer receiver type was found
|
||||
// but there was no pointer on the path from the actual receiver type to
|
||||
// the method's formal receiver base type, nor was the receiver addressable.
|
||||
//
|
||||
func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
|
||||
// Methods cannot be associated to a named pointer type
|
||||
// (spec: "The type denoted by T is called the receiver base type;
|
||||
// it must not be a pointer or interface type and it must be declared
|
||||
// in the same package as the method.").
|
||||
// Thus, if we have a named pointer type, proceed with the underlying
|
||||
// pointer type but discard the result if it is a method since we would
|
||||
// not have found it for T (see also issue 8590).
|
||||
if t, _ := T.(*Named); t != nil {
|
||||
if p, _ := t.underlying.(*Pointer); p != nil {
|
||||
obj, index, indirect = lookupFieldOrMethod(p, false, pkg, name)
|
||||
if _, ok := obj.(*Func); ok {
|
||||
return nil, nil, false
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return lookupFieldOrMethod(T, addressable, pkg, name)
|
||||
}
|
||||
|
||||
// TODO(gri) The named type consolidation and seen maps below must be
|
||||
// indexed by unique keys for a given type. Verify that named
|
||||
// types always have only one representation (even when imported
|
||||
// indirectly via different packages.)
|
||||
|
||||
func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
|
||||
// WARNING: The code in this function is extremely subtle - do not modify casually!
|
||||
// This function and NewMethodSet should be kept in sync.
|
||||
|
||||
if name == "_" {
|
||||
return // blank fields/methods are never found
|
||||
}
|
||||
|
||||
typ, isPtr := deref(T)
|
||||
|
||||
// *typ where typ is an interface has no methods.
|
||||
if isPtr && IsInterface(typ) {
|
||||
return
|
||||
}
|
||||
|
||||
// Start with typ as single entry at shallowest depth.
|
||||
current := []embeddedType{{typ, nil, isPtr, false}}
|
||||
|
||||
// Named types that we have seen already, allocated lazily.
|
||||
// Used to avoid endless searches in case of recursive types.
|
||||
// Since only Named types can be used for recursive types, we
|
||||
// only need to track those.
|
||||
// (If we ever allow type aliases to construct recursive types,
|
||||
// we must use type identity rather than pointer equality for
|
||||
// the map key comparison, as we do in consolidateMultiples.)
|
||||
var seen map[*Named]bool
|
||||
|
||||
// search current depth
|
||||
for len(current) > 0 {
|
||||
var next []embeddedType // embedded types found at current depth
|
||||
|
||||
// look for (pkg, name) in all types at current depth
|
||||
for _, e := range current {
|
||||
typ := e.typ
|
||||
|
||||
// If we have a named type, we may have associated methods.
|
||||
// Look for those first.
|
||||
if named, _ := typ.(*Named); named != nil {
|
||||
if seen[named] {
|
||||
// We have seen this type before, at a more shallow depth
|
||||
// (note that multiples of this type at the current depth
|
||||
// were consolidated before). The type at that depth shadows
|
||||
// this same type at the current depth, so we can ignore
|
||||
// this one.
|
||||
continue
|
||||
}
|
||||
if seen == nil {
|
||||
seen = make(map[*Named]bool)
|
||||
}
|
||||
seen[named] = true
|
||||
|
||||
// look for a matching attached method
|
||||
if i, m := lookupMethod(named.methods, pkg, name); m != nil {
|
||||
// potential match
|
||||
assert(m.typ != nil)
|
||||
index = concat(e.index, i)
|
||||
if obj != nil || e.multiples {
|
||||
return nil, index, false // collision
|
||||
}
|
||||
obj = m
|
||||
indirect = e.indirect
|
||||
continue // we can't have a matching field or interface method
|
||||
}
|
||||
|
||||
// continue with underlying type
|
||||
typ = named.underlying
|
||||
}
|
||||
|
||||
switch t := typ.(type) {
|
||||
case *Struct:
|
||||
// look for a matching field and collect embedded types
|
||||
for i, f := range t.fields {
|
||||
if f.sameId(pkg, name) {
|
||||
assert(f.typ != nil)
|
||||
index = concat(e.index, i)
|
||||
if obj != nil || e.multiples {
|
||||
return nil, index, false // collision
|
||||
}
|
||||
obj = f
|
||||
indirect = e.indirect
|
||||
continue // we can't have a matching interface method
|
||||
}
|
||||
// Collect embedded struct fields for searching the next
|
||||
// lower depth, but only if we have not seen a match yet
|
||||
// (if we have a match it is either the desired field or
|
||||
// we have a name collision on the same depth; in either
|
||||
// case we don't need to look further).
|
||||
// Embedded fields are always of the form T or *T where
|
||||
// T is a type name. If e.typ appeared multiple times at
|
||||
// this depth, f.typ appears multiple times at the next
|
||||
// depth.
|
||||
if obj == nil && f.anonymous {
|
||||
typ, isPtr := deref(f.typ)
|
||||
// TODO(gri) optimization: ignore types that can't
|
||||
// have fields or methods (only Named, Struct, and
|
||||
// Interface types need to be considered).
|
||||
next = append(next, embeddedType{typ, concat(e.index, i), e.indirect || isPtr, e.multiples})
|
||||
}
|
||||
}
|
||||
|
||||
case *Interface:
|
||||
// look for a matching method
|
||||
// TODO(gri) t.allMethods is sorted - use binary search
|
||||
if i, m := lookupMethod(t.allMethods, pkg, name); m != nil {
|
||||
assert(m.typ != nil)
|
||||
index = concat(e.index, i)
|
||||
if obj != nil || e.multiples {
|
||||
return nil, index, false // collision
|
||||
}
|
||||
obj = m
|
||||
indirect = e.indirect
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if obj != nil {
|
||||
// found a potential match
|
||||
// spec: "A method call x.m() is valid if the method set of (the type of) x
|
||||
// contains m and the argument list can be assigned to the parameter
|
||||
// list of m. If x is addressable and &x's method set contains m, x.m()
|
||||
// is shorthand for (&x).m()".
|
||||
if f, _ := obj.(*Func); f != nil && ptrRecv(f) && !indirect && !addressable {
|
||||
return nil, nil, true // pointer/addressable receiver required
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
current = consolidateMultiples(next)
|
||||
}
|
||||
|
||||
return nil, nil, false // not found
|
||||
}
|
||||
|
||||
// embeddedType represents an embedded type
|
||||
type embeddedType struct {
|
||||
typ Type
|
||||
index []int // embedded field indices, starting with index at depth 0
|
||||
indirect bool // if set, there was a pointer indirection on the path to this field
|
||||
multiples bool // if set, typ appears multiple times at this depth
|
||||
}
|
||||
|
||||
// consolidateMultiples collects multiple list entries with the same type
|
||||
// into a single entry marked as containing multiples. The result is the
|
||||
// consolidated list.
|
||||
func consolidateMultiples(list []embeddedType) []embeddedType {
|
||||
if len(list) <= 1 {
|
||||
return list // at most one entry - nothing to do
|
||||
}
|
||||
|
||||
n := 0 // number of entries w/ unique type
|
||||
prev := make(map[Type]int) // index at which type was previously seen
|
||||
for _, e := range list {
|
||||
if i, found := lookupType(prev, e.typ); found {
|
||||
list[i].multiples = true
|
||||
// ignore this entry
|
||||
} else {
|
||||
prev[e.typ] = n
|
||||
list[n] = e
|
||||
n++
|
||||
}
|
||||
}
|
||||
return list[:n]
|
||||
}
|
||||
|
||||
func lookupType(m map[Type]int, typ Type) (int, bool) {
|
||||
// fast path: maybe the types are equal
|
||||
if i, found := m[typ]; found {
|
||||
return i, true
|
||||
}
|
||||
|
||||
for t, i := range m {
|
||||
if Identical(t, typ) {
|
||||
return i, true
|
||||
}
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// MissingMethod returns (nil, false) if V implements T, otherwise it
|
||||
// returns a missing method required by T and whether it is missing or
|
||||
// just has the wrong type.
|
||||
//
|
||||
// For non-interface types V, or if static is set, V implements T if all
|
||||
// methods of T are present in V. Otherwise (V is an interface and static
|
||||
// is not set), MissingMethod only checks that methods of T which are also
|
||||
// present in V have matching types (e.g., for a type assertion x.(T) where
|
||||
// x is of interface type V).
|
||||
//
|
||||
func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType bool) {
|
||||
// fast path for common case
|
||||
if T.Empty() {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(gri) Consider using method sets here. Might be more efficient.
|
||||
|
||||
if ityp, _ := V.Underlying().(*Interface); ityp != nil {
|
||||
// TODO(gri) allMethods is sorted - can do this more efficiently
|
||||
for _, m := range T.allMethods {
|
||||
_, obj := lookupMethod(ityp.allMethods, m.pkg, m.name)
|
||||
switch {
|
||||
case obj == nil:
|
||||
if static {
|
||||
return m, false
|
||||
}
|
||||
case !Identical(obj.Type(), m.typ):
|
||||
return m, true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// A concrete type implements T if it implements all methods of T.
|
||||
for _, m := range T.allMethods {
|
||||
obj, _, _ := lookupFieldOrMethod(V, false, m.pkg, m.name)
|
||||
|
||||
f, _ := obj.(*Func)
|
||||
if f == nil {
|
||||
return m, false
|
||||
}
|
||||
|
||||
if !Identical(f.typ, m.typ) {
|
||||
return m, true
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// assertableTo reports whether a value of type V can be asserted to have type T.
|
||||
// It returns (nil, false) as affirmative answer. Otherwise it returns a missing
|
||||
// method required by V and whether it is missing or just has the wrong type.
|
||||
func assertableTo(V *Interface, T Type) (method *Func, wrongType bool) {
|
||||
// no static check is required if T is an interface
|
||||
// spec: "If T is an interface type, x.(T) asserts that the
|
||||
// dynamic type of x implements the interface T."
|
||||
if _, ok := T.Underlying().(*Interface); ok && !strict {
|
||||
return
|
||||
}
|
||||
return MissingMethod(T, V, false)
|
||||
}
|
||||
|
||||
// deref dereferences typ if it is a *Pointer and returns its base and true.
|
||||
// Otherwise it returns (typ, false).
|
||||
func deref(typ Type) (Type, bool) {
|
||||
if p, _ := typ.(*Pointer); p != nil {
|
||||
return p.base, true
|
||||
}
|
||||
return typ, false
|
||||
}
|
||||
|
||||
// derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a
|
||||
// (named or unnamed) struct and returns its base. Otherwise it returns typ.
|
||||
func derefStructPtr(typ Type) Type {
|
||||
if p, _ := typ.Underlying().(*Pointer); p != nil {
|
||||
if _, ok := p.base.Underlying().(*Struct); ok {
|
||||
return p.base
|
||||
}
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
// concat returns the result of concatenating list and i.
|
||||
// The result does not share its underlying array with list.
|
||||
func concat(list []int, i int) []int {
|
||||
var t []int
|
||||
t = append(t, list...)
|
||||
return append(t, i)
|
||||
}
|
||||
|
||||
// fieldIndex returns the index for the field with matching package and name, or a value < 0.
|
||||
func fieldIndex(fields []*Var, pkg *Package, name string) int {
|
||||
if name != "_" {
|
||||
for i, f := range fields {
|
||||
if f.sameId(pkg, name) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// lookupMethod returns the index of and method with matching package and name, or (-1, nil).
|
||||
func lookupMethod(methods []*Func, pkg *Package, name string) (int, *Func) {
|
||||
if name != "_" {
|
||||
for i, m := range methods {
|
||||
if m.sameId(pkg, name) {
|
||||
return i, m
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
262
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/methodset.go
generated
vendored
262
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/methodset.go
generated
vendored
@ -1,262 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements method sets.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// A MethodSet is an ordered set of concrete or abstract (interface) methods;
|
||||
// a method is a MethodVal selection, and they are ordered by ascending m.Obj().Id().
|
||||
// The zero value for a MethodSet is a ready-to-use empty method set.
|
||||
type MethodSet struct {
|
||||
list []*Selection
|
||||
}
|
||||
|
||||
func (s *MethodSet) String() string {
|
||||
if s.Len() == 0 {
|
||||
return "MethodSet {}"
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintln(&buf, "MethodSet {")
|
||||
for _, f := range s.list {
|
||||
fmt.Fprintf(&buf, "\t%s\n", f)
|
||||
}
|
||||
fmt.Fprintln(&buf, "}")
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// Len returns the number of methods in s.
|
||||
func (s *MethodSet) Len() int { return len(s.list) }
|
||||
|
||||
// At returns the i'th method in s for 0 <= i < s.Len().
|
||||
func (s *MethodSet) At(i int) *Selection { return s.list[i] }
|
||||
|
||||
// Lookup returns the method with matching package and name, or nil if not found.
|
||||
func (s *MethodSet) Lookup(pkg *Package, name string) *Selection {
|
||||
if s.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
key := Id(pkg, name)
|
||||
i := sort.Search(len(s.list), func(i int) bool {
|
||||
m := s.list[i]
|
||||
return m.obj.Id() >= key
|
||||
})
|
||||
if i < len(s.list) {
|
||||
m := s.list[i]
|
||||
if m.obj.Id() == key {
|
||||
return m
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shared empty method set.
|
||||
var emptyMethodSet MethodSet
|
||||
|
||||
// NewMethodSet returns the method set for the given type T.
|
||||
// It always returns a non-nil method set, even if it is empty.
|
||||
func NewMethodSet(T Type) *MethodSet {
|
||||
// WARNING: The code in this function is extremely subtle - do not modify casually!
|
||||
// This function and lookupFieldOrMethod should be kept in sync.
|
||||
|
||||
// method set up to the current depth, allocated lazily
|
||||
var base methodSet
|
||||
|
||||
typ, isPtr := deref(T)
|
||||
|
||||
// *typ where typ is an interface has no methods.
|
||||
if isPtr && IsInterface(typ) {
|
||||
return &emptyMethodSet
|
||||
}
|
||||
|
||||
// Start with typ as single entry at shallowest depth.
|
||||
current := []embeddedType{{typ, nil, isPtr, false}}
|
||||
|
||||
// Named types that we have seen already, allocated lazily.
|
||||
// Used to avoid endless searches in case of recursive types.
|
||||
// Since only Named types can be used for recursive types, we
|
||||
// only need to track those.
|
||||
// (If we ever allow type aliases to construct recursive types,
|
||||
// we must use type identity rather than pointer equality for
|
||||
// the map key comparison, as we do in consolidateMultiples.)
|
||||
var seen map[*Named]bool
|
||||
|
||||
// collect methods at current depth
|
||||
for len(current) > 0 {
|
||||
var next []embeddedType // embedded types found at current depth
|
||||
|
||||
// field and method sets at current depth, allocated lazily
|
||||
var fset fieldSet
|
||||
var mset methodSet
|
||||
|
||||
for _, e := range current {
|
||||
typ := e.typ
|
||||
|
||||
// If we have a named type, we may have associated methods.
|
||||
// Look for those first.
|
||||
if named, _ := typ.(*Named); named != nil {
|
||||
if seen[named] {
|
||||
// We have seen this type before, at a more shallow depth
|
||||
// (note that multiples of this type at the current depth
|
||||
// were consolidated before). The type at that depth shadows
|
||||
// this same type at the current depth, so we can ignore
|
||||
// this one.
|
||||
continue
|
||||
}
|
||||
if seen == nil {
|
||||
seen = make(map[*Named]bool)
|
||||
}
|
||||
seen[named] = true
|
||||
|
||||
mset = mset.add(named.methods, e.index, e.indirect, e.multiples)
|
||||
|
||||
// continue with underlying type
|
||||
typ = named.underlying
|
||||
}
|
||||
|
||||
switch t := typ.(type) {
|
||||
case *Struct:
|
||||
for i, f := range t.fields {
|
||||
fset = fset.add(f, e.multiples)
|
||||
|
||||
// Embedded fields are always of the form T or *T where
|
||||
// T is a type name. If typ appeared multiple times at
|
||||
// this depth, f.Type appears multiple times at the next
|
||||
// depth.
|
||||
if f.anonymous {
|
||||
typ, isPtr := deref(f.typ)
|
||||
// TODO(gri) optimization: ignore types that can't
|
||||
// have fields or methods (only Named, Struct, and
|
||||
// Interface types need to be considered).
|
||||
next = append(next, embeddedType{typ, concat(e.index, i), e.indirect || isPtr, e.multiples})
|
||||
}
|
||||
}
|
||||
|
||||
case *Interface:
|
||||
mset = mset.add(t.allMethods, e.index, true, e.multiples)
|
||||
}
|
||||
}
|
||||
|
||||
// Add methods and collisions at this depth to base if no entries with matching
|
||||
// names exist already.
|
||||
for k, m := range mset {
|
||||
if _, found := base[k]; !found {
|
||||
// Fields collide with methods of the same name at this depth.
|
||||
if _, found := fset[k]; found {
|
||||
m = nil // collision
|
||||
}
|
||||
if base == nil {
|
||||
base = make(methodSet)
|
||||
}
|
||||
base[k] = m
|
||||
}
|
||||
}
|
||||
|
||||
// Multiple fields with matching names collide at this depth and shadow all
|
||||
// entries further down; add them as collisions to base if no entries with
|
||||
// matching names exist already.
|
||||
for k, f := range fset {
|
||||
if f == nil {
|
||||
if _, found := base[k]; !found {
|
||||
if base == nil {
|
||||
base = make(methodSet)
|
||||
}
|
||||
base[k] = nil // collision
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current = consolidateMultiples(next)
|
||||
}
|
||||
|
||||
if len(base) == 0 {
|
||||
return &emptyMethodSet
|
||||
}
|
||||
|
||||
// collect methods
|
||||
var list []*Selection
|
||||
for _, m := range base {
|
||||
if m != nil {
|
||||
m.recv = T
|
||||
list = append(list, m)
|
||||
}
|
||||
}
|
||||
// sort by unique name
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
return list[i].obj.Id() < list[j].obj.Id()
|
||||
})
|
||||
return &MethodSet{list}
|
||||
}
|
||||
|
||||
// A fieldSet is a set of fields and name collisions.
|
||||
// A collision indicates that multiple fields with the
|
||||
// same unique id appeared.
|
||||
type fieldSet map[string]*Var // a nil entry indicates a name collision
|
||||
|
||||
// Add adds field f to the field set s.
|
||||
// If multiples is set, f appears multiple times
|
||||
// and is treated as a collision.
|
||||
func (s fieldSet) add(f *Var, multiples bool) fieldSet {
|
||||
if s == nil {
|
||||
s = make(fieldSet)
|
||||
}
|
||||
key := f.Id()
|
||||
// if f is not in the set, add it
|
||||
if !multiples {
|
||||
if _, found := s[key]; !found {
|
||||
s[key] = f
|
||||
return s
|
||||
}
|
||||
}
|
||||
s[key] = nil // collision
|
||||
return s
|
||||
}
|
||||
|
||||
// A methodSet is a set of methods and name collisions.
|
||||
// A collision indicates that multiple methods with the
|
||||
// same unique id appeared.
|
||||
type methodSet map[string]*Selection // a nil entry indicates a name collision
|
||||
|
||||
// Add adds all functions in list to the method set s.
|
||||
// If multiples is set, every function in list appears multiple times
|
||||
// and is treated as a collision.
|
||||
func (s methodSet) add(list []*Func, index []int, indirect bool, multiples bool) methodSet {
|
||||
if len(list) == 0 {
|
||||
return s
|
||||
}
|
||||
if s == nil {
|
||||
s = make(methodSet)
|
||||
}
|
||||
for i, f := range list {
|
||||
key := f.Id()
|
||||
// if f is not in the set, add it
|
||||
if !multiples {
|
||||
// TODO(gri) A found method may not be added because it's not in the method set
|
||||
// (!indirect && ptrRecv(f)). A 2nd method on the same level may be in the method
|
||||
// set and may not collide with the first one, thus leading to a false positive.
|
||||
// Is that possible? Investigate.
|
||||
if _, found := s[key]; !found && (indirect || !ptrRecv(f)) {
|
||||
s[key] = &Selection{MethodVal, nil, f, concat(index, i), indirect}
|
||||
continue
|
||||
}
|
||||
}
|
||||
s[key] = nil // collision
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// ptrRecv reports whether the receiver is of the form *T.
|
||||
// The receiver must exist.
|
||||
func ptrRecv(f *Func) bool {
|
||||
_, isPtr := deref(f.typ.(*Signature).recv.typ)
|
||||
return isPtr
|
||||
}
|
424
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/object.go
generated
vendored
424
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/object.go
generated
vendored
@ -1,424 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// An Object describes a named language entity such as a package,
|
||||
// constant, type, variable, function (incl. methods), or label.
|
||||
// All objects implement the Object interface.
|
||||
//
|
||||
type Object interface {
|
||||
Parent() *Scope // scope in which this object is declared; nil for methods and struct fields
|
||||
Pos() token.Pos // position of object identifier in declaration
|
||||
Pkg() *Package // package to which this object belongs; nil for labels and objects in the Universe scope
|
||||
Name() string // package local object name
|
||||
Type() Type // object type
|
||||
Exported() bool // reports whether the name starts with a capital letter
|
||||
Id() string // object name if exported, qualified name if not exported (see func Id)
|
||||
|
||||
// String returns a human-readable string of the object.
|
||||
String() string
|
||||
|
||||
// order reflects a package-level object's source order: if object
|
||||
// a is before object b in the source, then a.order() < b.order().
|
||||
// order returns a value > 0 for package-level objects; it returns
|
||||
// 0 for all other objects (including objects in file scopes).
|
||||
order() uint32
|
||||
|
||||
// setOrder sets the order number of the object. It must be > 0.
|
||||
setOrder(uint32)
|
||||
|
||||
// setParent sets the parent scope of the object.
|
||||
setParent(*Scope)
|
||||
|
||||
// sameId reports whether obj.Id() and Id(pkg, name) are the same.
|
||||
sameId(pkg *Package, name string) bool
|
||||
|
||||
// scopePos returns the start position of the scope of this Object
|
||||
scopePos() token.Pos
|
||||
|
||||
// setScopePos sets the start position of the scope for this Object.
|
||||
setScopePos(pos token.Pos)
|
||||
}
|
||||
|
||||
// Id returns name if it is exported, otherwise it
|
||||
// returns the name qualified with the package path.
|
||||
func Id(pkg *Package, name string) string {
|
||||
if ast.IsExported(name) {
|
||||
return name
|
||||
}
|
||||
// unexported names need the package path for differentiation
|
||||
// (if there's no package, make sure we don't start with '.'
|
||||
// as that may change the order of methods between a setup
|
||||
// inside a package and outside a package - which breaks some
|
||||
// tests)
|
||||
path := "_"
|
||||
// pkg is nil for objects in Universe scope and possibly types
|
||||
// introduced via Eval (see also comment in object.sameId)
|
||||
if pkg != nil && pkg.path != "" {
|
||||
path = pkg.path
|
||||
}
|
||||
return path + "." + name
|
||||
}
|
||||
|
||||
// An object implements the common parts of an Object.
|
||||
type object struct {
|
||||
parent *Scope
|
||||
pos token.Pos
|
||||
pkg *Package
|
||||
name string
|
||||
typ Type
|
||||
order_ uint32
|
||||
scopePos_ token.Pos
|
||||
}
|
||||
|
||||
func (obj *object) Parent() *Scope { return obj.parent }
|
||||
func (obj *object) Pos() token.Pos { return obj.pos }
|
||||
func (obj *object) Pkg() *Package { return obj.pkg }
|
||||
func (obj *object) Name() string { return obj.name }
|
||||
func (obj *object) Type() Type { return obj.typ }
|
||||
func (obj *object) Exported() bool { return ast.IsExported(obj.name) }
|
||||
func (obj *object) Id() string { return Id(obj.pkg, obj.name) }
|
||||
func (obj *object) String() string { panic("abstract") }
|
||||
func (obj *object) order() uint32 { return obj.order_ }
|
||||
func (obj *object) scopePos() token.Pos { return obj.scopePos_ }
|
||||
|
||||
func (obj *object) setParent(parent *Scope) { obj.parent = parent }
|
||||
func (obj *object) setOrder(order uint32) { assert(order > 0); obj.order_ = order }
|
||||
func (obj *object) setScopePos(pos token.Pos) { obj.scopePos_ = pos }
|
||||
|
||||
func (obj *object) sameId(pkg *Package, name string) bool {
|
||||
// spec:
|
||||
// "Two identifiers are different if they are spelled differently,
|
||||
// or if they appear in different packages and are not exported.
|
||||
// Otherwise, they are the same."
|
||||
if name != obj.name {
|
||||
return false
|
||||
}
|
||||
// obj.Name == name
|
||||
if obj.Exported() {
|
||||
return true
|
||||
}
|
||||
// not exported, so packages must be the same (pkg == nil for
|
||||
// fields in Universe scope; this can only happen for types
|
||||
// introduced via Eval)
|
||||
if pkg == nil || obj.pkg == nil {
|
||||
return pkg == obj.pkg
|
||||
}
|
||||
// pkg != nil && obj.pkg != nil
|
||||
return pkg.path == obj.pkg.path
|
||||
}
|
||||
|
||||
// A PkgName represents an imported Go package.
|
||||
// PkgNames don't have a type.
|
||||
type PkgName struct {
|
||||
object
|
||||
imported *Package
|
||||
used bool // set if the package was used
|
||||
}
|
||||
|
||||
// NewPkgName returns a new PkgName object representing an imported package.
|
||||
// The remaining arguments set the attributes found with all Objects.
|
||||
func NewPkgName(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName {
|
||||
return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, token.NoPos}, imported, false}
|
||||
}
|
||||
|
||||
// Imported returns the package that was imported.
|
||||
// It is distinct from Pkg(), which is the package containing the import statement.
|
||||
func (obj *PkgName) Imported() *Package { return obj.imported }
|
||||
|
||||
// A Const represents a declared constant.
|
||||
type Const struct {
|
||||
object
|
||||
val constant.Value
|
||||
visited bool // for initialization cycle detection
|
||||
}
|
||||
|
||||
// NewConst returns a new constant with value val.
|
||||
// The remaining arguments set the attributes found with all Objects.
|
||||
func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val constant.Value) *Const {
|
||||
return &Const{object{nil, pos, pkg, name, typ, 0, token.NoPos}, val, false}
|
||||
}
|
||||
|
||||
func (obj *Const) Val() constant.Value { return obj.val }
|
||||
func (*Const) isDependency() {} // a constant may be a dependency of an initialization expression
|
||||
|
||||
// A TypeName represents a name for a (named or alias) type.
|
||||
type TypeName struct {
|
||||
object
|
||||
}
|
||||
|
||||
// NewTypeName returns a new type name denoting the given typ.
|
||||
// The remaining arguments set the attributes found with all Objects.
|
||||
//
|
||||
// The typ argument may be a defined (Named) type or an alias type.
|
||||
// It may also be nil such that the returned TypeName can be used as
|
||||
// argument for NewNamed, which will set the TypeName's type as a side-
|
||||
// effect.
|
||||
func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
|
||||
return &TypeName{object{nil, pos, pkg, name, typ, 0, token.NoPos}}
|
||||
}
|
||||
|
||||
// IsAlias reports whether obj is an alias name for a type.
|
||||
func (obj *TypeName) IsAlias() bool {
|
||||
switch t := obj.typ.(type) {
|
||||
case nil:
|
||||
return false
|
||||
case *Basic:
|
||||
// unsafe.Pointer is not an alias.
|
||||
if obj.pkg == Unsafe {
|
||||
return false
|
||||
}
|
||||
// Any user-defined type name for a basic type is an alias for a
|
||||
// basic type (because basic types are pre-declared in the Universe
|
||||
// scope, outside any package scope), and so is any type name with
|
||||
// a different name than the name of the basic type it refers to.
|
||||
// Additionally, we need to look for "byte" and "rune" because they
|
||||
// are aliases but have the same names (for better error messages).
|
||||
return obj.pkg != nil || t.name != obj.name || t == universeByte || t == universeRune
|
||||
case *Named:
|
||||
return obj != t.obj
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// A Variable represents a declared variable (including function parameters and results, and struct fields).
|
||||
type Var struct {
|
||||
object
|
||||
anonymous bool // if set, the variable is an anonymous struct field, and name is the type name
|
||||
visited bool // for initialization cycle detection
|
||||
isField bool // var is struct field
|
||||
used bool // set if the variable was used
|
||||
}
|
||||
|
||||
// NewVar returns a new variable.
|
||||
// The arguments set the attributes found with all Objects.
|
||||
func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
|
||||
return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}}
|
||||
}
|
||||
|
||||
// NewParam returns a new variable representing a function parameter.
|
||||
func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
|
||||
return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, used: true} // parameters are always 'used'
|
||||
}
|
||||
|
||||
// NewField returns a new variable representing a struct field.
|
||||
// For anonymous (embedded) fields, the name is the unqualified
|
||||
// type name under which the field is accessible.
|
||||
func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var {
|
||||
return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, anonymous: anonymous, isField: true}
|
||||
}
|
||||
|
||||
// Anonymous reports whether the variable is an anonymous field.
|
||||
func (obj *Var) Anonymous() bool { return obj.anonymous }
|
||||
|
||||
// IsField reports whether the variable is a struct field.
|
||||
func (obj *Var) IsField() bool { return obj.isField }
|
||||
|
||||
func (*Var) isDependency() {} // a variable may be a dependency of an initialization expression
|
||||
|
||||
// A Func represents a declared function, concrete method, or abstract
|
||||
// (interface) method. Its Type() is always a *Signature.
|
||||
// An abstract method may belong to many interfaces due to embedding.
|
||||
type Func struct {
|
||||
object
|
||||
}
|
||||
|
||||
// NewFunc returns a new function with the given signature, representing
|
||||
// the function's type.
|
||||
func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
|
||||
// don't store a nil signature
|
||||
var typ Type
|
||||
if sig != nil {
|
||||
typ = sig
|
||||
}
|
||||
return &Func{object{nil, pos, pkg, name, typ, 0, token.NoPos}}
|
||||
}
|
||||
|
||||
// FullName returns the package- or receiver-type-qualified name of
|
||||
// function or method obj.
|
||||
func (obj *Func) FullName() string {
|
||||
var buf bytes.Buffer
|
||||
writeFuncName(&buf, obj, nil)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// Scope returns the scope of the function's body block.
|
||||
func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
|
||||
|
||||
func (*Func) isDependency() {} // a function may be a dependency of an initialization expression
|
||||
|
||||
// A Label represents a declared label.
|
||||
// Labels don't have a type.
|
||||
type Label struct {
|
||||
object
|
||||
used bool // set if the label was used
|
||||
}
|
||||
|
||||
// NewLabel returns a new label.
|
||||
func NewLabel(pos token.Pos, pkg *Package, name string) *Label {
|
||||
return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid]}, false}
|
||||
}
|
||||
|
||||
// A Builtin represents a built-in function.
|
||||
// Builtins don't have a valid type.
|
||||
type Builtin struct {
|
||||
object
|
||||
id builtinId
|
||||
}
|
||||
|
||||
func newBuiltin(id builtinId) *Builtin {
|
||||
return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid]}, id}
|
||||
}
|
||||
|
||||
// Nil represents the predeclared value nil.
|
||||
type Nil struct {
|
||||
object
|
||||
}
|
||||
|
||||
func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
|
||||
var tname *TypeName
|
||||
typ := obj.Type()
|
||||
|
||||
switch obj := obj.(type) {
|
||||
case *PkgName:
|
||||
fmt.Fprintf(buf, "package %s", obj.Name())
|
||||
if path := obj.imported.path; path != "" && path != obj.name {
|
||||
fmt.Fprintf(buf, " (%q)", path)
|
||||
}
|
||||
return
|
||||
|
||||
case *Const:
|
||||
buf.WriteString("const")
|
||||
|
||||
case *TypeName:
|
||||
tname = obj
|
||||
buf.WriteString("type")
|
||||
|
||||
case *Var:
|
||||
if obj.isField {
|
||||
buf.WriteString("field")
|
||||
} else {
|
||||
buf.WriteString("var")
|
||||
}
|
||||
|
||||
case *Func:
|
||||
buf.WriteString("func ")
|
||||
writeFuncName(buf, obj, qf)
|
||||
if typ != nil {
|
||||
WriteSignature(buf, typ.(*Signature), qf)
|
||||
}
|
||||
return
|
||||
|
||||
case *Label:
|
||||
buf.WriteString("label")
|
||||
typ = nil
|
||||
|
||||
case *Builtin:
|
||||
buf.WriteString("builtin")
|
||||
typ = nil
|
||||
|
||||
case *Nil:
|
||||
buf.WriteString("nil")
|
||||
return
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("writeObject(%T)", obj))
|
||||
}
|
||||
|
||||
buf.WriteByte(' ')
|
||||
|
||||
// For package-level objects, qualify the name.
|
||||
if obj.Pkg() != nil && obj.Pkg().scope.Lookup(obj.Name()) == obj {
|
||||
writePackage(buf, obj.Pkg(), qf)
|
||||
}
|
||||
buf.WriteString(obj.Name())
|
||||
|
||||
if typ == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if tname != nil {
|
||||
// We have a type object: Don't print anything more for
|
||||
// basic types since there's no more information (names
|
||||
// are the same; see also comment in TypeName.IsAlias).
|
||||
if _, ok := typ.(*Basic); ok {
|
||||
return
|
||||
}
|
||||
if tname.IsAlias() {
|
||||
buf.WriteString(" =")
|
||||
} else {
|
||||
typ = typ.Underlying()
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteByte(' ')
|
||||
WriteType(buf, typ, qf)
|
||||
}
|
||||
|
||||
func writePackage(buf *bytes.Buffer, pkg *Package, qf Qualifier) {
|
||||
if pkg == nil {
|
||||
return
|
||||
}
|
||||
var s string
|
||||
if qf != nil {
|
||||
s = qf(pkg)
|
||||
} else {
|
||||
s = pkg.Path()
|
||||
}
|
||||
if s != "" {
|
||||
buf.WriteString(s)
|
||||
buf.WriteByte('.')
|
||||
}
|
||||
}
|
||||
|
||||
// ObjectString returns the string form of obj.
|
||||
// The Qualifier controls the printing of
|
||||
// package-level objects, and may be nil.
|
||||
func ObjectString(obj Object, qf Qualifier) string {
|
||||
var buf bytes.Buffer
|
||||
writeObject(&buf, obj, qf)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (obj *PkgName) String() string { return ObjectString(obj, nil) }
|
||||
func (obj *Const) String() string { return ObjectString(obj, nil) }
|
||||
func (obj *TypeName) String() string { return ObjectString(obj, nil) }
|
||||
func (obj *Var) String() string { return ObjectString(obj, nil) }
|
||||
func (obj *Func) String() string { return ObjectString(obj, nil) }
|
||||
func (obj *Label) String() string { return ObjectString(obj, nil) }
|
||||
func (obj *Builtin) String() string { return ObjectString(obj, nil) }
|
||||
func (obj *Nil) String() string { return ObjectString(obj, nil) }
|
||||
|
||||
func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) {
|
||||
if f.typ != nil {
|
||||
sig := f.typ.(*Signature)
|
||||
if recv := sig.Recv(); recv != nil {
|
||||
buf.WriteByte('(')
|
||||
if _, ok := recv.Type().(*Interface); ok {
|
||||
// gcimporter creates abstract methods of
|
||||
// named interfaces using the interface type
|
||||
// (not the named type) as the receiver.
|
||||
// Don't print it in full.
|
||||
buf.WriteString("interface")
|
||||
} else {
|
||||
WriteType(buf, recv.Type(), qf)
|
||||
}
|
||||
buf.WriteByte(')')
|
||||
buf.WriteByte('.')
|
||||
} else if f.pkg != nil {
|
||||
writePackage(buf, f.pkg, qf)
|
||||
}
|
||||
}
|
||||
buf.WriteString(f.name)
|
||||
}
|
31
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/objset.go
generated
vendored
31
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/objset.go
generated
vendored
@ -1,31 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements objsets.
|
||||
//
|
||||
// An objset is similar to a Scope but objset elements
|
||||
// are identified by their unique id, instead of their
|
||||
// object name.
|
||||
|
||||
package types
|
||||
|
||||
// An objset is a set of objects identified by their unique id.
|
||||
// The zero value for objset is a ready-to-use empty objset.
|
||||
type objset map[string]Object // initialized lazily
|
||||
|
||||
// insert attempts to insert an object obj into objset s.
|
||||
// If s already contains an alternative object alt with
|
||||
// the same name, insert leaves s unchanged and returns alt.
|
||||
// Otherwise it inserts obj and returns nil.
|
||||
func (s *objset) insert(obj Object) Object {
|
||||
id := obj.Id()
|
||||
if alt := (*s)[id]; alt != nil {
|
||||
return alt
|
||||
}
|
||||
if *s == nil {
|
||||
*s = make(map[string]Object)
|
||||
}
|
||||
(*s)[id] = obj
|
||||
return nil
|
||||
}
|
275
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/operand.go
generated
vendored
275
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/operand.go
generated
vendored
@ -1,275 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file defines operands and associated operations.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// An operandMode specifies the (addressing) mode of an operand.
|
||||
type operandMode byte
|
||||
|
||||
const (
|
||||
invalid operandMode = iota // operand is invalid
|
||||
novalue // operand represents no value (result of a function call w/o result)
|
||||
builtin // operand is a built-in function
|
||||
typexpr // operand is a type
|
||||
constant_ // operand is a constant; the operand's typ is a Basic type
|
||||
variable // operand is an addressable variable
|
||||
mapindex // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment)
|
||||
value // operand is a computed value
|
||||
commaok // like value, but operand may be used in a comma,ok expression
|
||||
)
|
||||
|
||||
var operandModeString = [...]string{
|
||||
invalid: "invalid operand",
|
||||
novalue: "no value",
|
||||
builtin: "built-in",
|
||||
typexpr: "type",
|
||||
constant_: "constant",
|
||||
variable: "variable",
|
||||
mapindex: "map index expression",
|
||||
value: "value",
|
||||
commaok: "comma, ok expression",
|
||||
}
|
||||
|
||||
// An operand represents an intermediate value during type checking.
|
||||
// Operands have an (addressing) mode, the expression evaluating to
|
||||
// the operand, the operand's type, a value for constants, and an id
|
||||
// for built-in functions.
|
||||
// The zero value of operand is a ready to use invalid operand.
|
||||
//
|
||||
type operand struct {
|
||||
mode operandMode
|
||||
expr ast.Expr
|
||||
typ Type
|
||||
val constant.Value
|
||||
id builtinId
|
||||
}
|
||||
|
||||
// pos returns the position of the expression corresponding to x.
|
||||
// If x is invalid the position is token.NoPos.
|
||||
//
|
||||
func (x *operand) pos() token.Pos {
|
||||
// x.expr may not be set if x is invalid
|
||||
if x.expr == nil {
|
||||
return token.NoPos
|
||||
}
|
||||
return x.expr.Pos()
|
||||
}
|
||||
|
||||
// Operand string formats
|
||||
// (not all "untyped" cases can appear due to the type system,
|
||||
// but they fall out naturally here)
|
||||
//
|
||||
// mode format
|
||||
//
|
||||
// invalid <expr> ( <mode> )
|
||||
// novalue <expr> ( <mode> )
|
||||
// builtin <expr> ( <mode> )
|
||||
// typexpr <expr> ( <mode> )
|
||||
//
|
||||
// constant <expr> (<untyped kind> <mode> )
|
||||
// constant <expr> ( <mode> of type <typ>)
|
||||
// constant <expr> (<untyped kind> <mode> <val> )
|
||||
// constant <expr> ( <mode> <val> of type <typ>)
|
||||
//
|
||||
// variable <expr> (<untyped kind> <mode> )
|
||||
// variable <expr> ( <mode> of type <typ>)
|
||||
//
|
||||
// mapindex <expr> (<untyped kind> <mode> )
|
||||
// mapindex <expr> ( <mode> of type <typ>)
|
||||
//
|
||||
// value <expr> (<untyped kind> <mode> )
|
||||
// value <expr> ( <mode> of type <typ>)
|
||||
//
|
||||
// commaok <expr> (<untyped kind> <mode> )
|
||||
// commaok <expr> ( <mode> of type <typ>)
|
||||
//
|
||||
func operandString(x *operand, qf Qualifier) string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
var expr string
|
||||
if x.expr != nil {
|
||||
expr = ExprString(x.expr)
|
||||
} else {
|
||||
switch x.mode {
|
||||
case builtin:
|
||||
expr = predeclaredFuncs[x.id].name
|
||||
case typexpr:
|
||||
expr = TypeString(x.typ, qf)
|
||||
case constant_:
|
||||
expr = x.val.String()
|
||||
}
|
||||
}
|
||||
|
||||
// <expr> (
|
||||
if expr != "" {
|
||||
buf.WriteString(expr)
|
||||
buf.WriteString(" (")
|
||||
}
|
||||
|
||||
// <untyped kind>
|
||||
hasType := false
|
||||
switch x.mode {
|
||||
case invalid, novalue, builtin, typexpr:
|
||||
// no type
|
||||
default:
|
||||
// should have a type, but be cautious (don't crash during printing)
|
||||
if x.typ != nil {
|
||||
if isUntyped(x.typ) {
|
||||
buf.WriteString(x.typ.(*Basic).name)
|
||||
buf.WriteByte(' ')
|
||||
break
|
||||
}
|
||||
hasType = true
|
||||
}
|
||||
}
|
||||
|
||||
// <mode>
|
||||
buf.WriteString(operandModeString[x.mode])
|
||||
|
||||
// <val>
|
||||
if x.mode == constant_ {
|
||||
if s := x.val.String(); s != expr {
|
||||
buf.WriteByte(' ')
|
||||
buf.WriteString(s)
|
||||
}
|
||||
}
|
||||
|
||||
// <typ>
|
||||
if hasType {
|
||||
if x.typ != Typ[Invalid] {
|
||||
buf.WriteString(" of type ")
|
||||
WriteType(&buf, x.typ, qf)
|
||||
} else {
|
||||
buf.WriteString(" with invalid type")
|
||||
}
|
||||
}
|
||||
|
||||
// )
|
||||
if expr != "" {
|
||||
buf.WriteByte(')')
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (x *operand) String() string {
|
||||
return operandString(x, nil)
|
||||
}
|
||||
|
||||
// setConst sets x to the untyped constant for literal lit.
|
||||
func (x *operand) setConst(tok token.Token, lit string) {
|
||||
var kind BasicKind
|
||||
switch tok {
|
||||
case token.INT:
|
||||
kind = UntypedInt
|
||||
case token.FLOAT:
|
||||
kind = UntypedFloat
|
||||
case token.IMAG:
|
||||
kind = UntypedComplex
|
||||
case token.CHAR:
|
||||
kind = UntypedRune
|
||||
case token.STRING:
|
||||
kind = UntypedString
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
|
||||
x.mode = constant_
|
||||
x.typ = Typ[kind]
|
||||
x.val = constant.MakeFromLiteral(lit, tok, 0)
|
||||
}
|
||||
|
||||
// isNil reports whether x is the nil value.
|
||||
func (x *operand) isNil() bool {
|
||||
return x.mode == value && x.typ == Typ[UntypedNil]
|
||||
}
|
||||
|
||||
// TODO(gri) The functions operand.assignableTo, checker.convertUntyped,
|
||||
// checker.representable, and checker.assignment are
|
||||
// overlapping in functionality. Need to simplify and clean up.
|
||||
|
||||
// assignableTo reports whether x is assignable to a variable of type T.
|
||||
// If the result is false and a non-nil reason is provided, it may be set
|
||||
// to a more detailed explanation of the failure (result != "").
|
||||
func (x *operand) assignableTo(conf *Config, T Type, reason *string) bool {
|
||||
if x.mode == invalid || T == Typ[Invalid] {
|
||||
return true // avoid spurious errors
|
||||
}
|
||||
|
||||
V := x.typ
|
||||
|
||||
// x's type is identical to T
|
||||
if Identical(V, T) {
|
||||
return true
|
||||
}
|
||||
|
||||
Vu := V.Underlying()
|
||||
Tu := T.Underlying()
|
||||
|
||||
// x is an untyped value representable by a value of type T
|
||||
// TODO(gri) This is borrowing from checker.convertUntyped and
|
||||
// checker.representable. Need to clean up.
|
||||
if isUntyped(Vu) {
|
||||
switch t := Tu.(type) {
|
||||
case *Basic:
|
||||
if x.isNil() && t.kind == UnsafePointer {
|
||||
return true
|
||||
}
|
||||
if x.mode == constant_ {
|
||||
return representableConst(x.val, conf, t, nil)
|
||||
}
|
||||
// The result of a comparison is an untyped boolean,
|
||||
// but may not be a constant.
|
||||
if Vb, _ := Vu.(*Basic); Vb != nil {
|
||||
return Vb.kind == UntypedBool && isBoolean(Tu)
|
||||
}
|
||||
case *Interface:
|
||||
return x.isNil() || t.Empty()
|
||||
case *Pointer, *Signature, *Slice, *Map, *Chan:
|
||||
return x.isNil()
|
||||
}
|
||||
}
|
||||
// Vu is typed
|
||||
|
||||
// x's type V and T have identical underlying types
|
||||
// and at least one of V or T is not a named type
|
||||
if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// T is an interface type and x implements T
|
||||
if Ti, ok := Tu.(*Interface); ok {
|
||||
if m, wrongType := MissingMethod(x.typ, Ti, true); m != nil /* Implements(x.typ, Ti) */ {
|
||||
if reason != nil {
|
||||
if wrongType {
|
||||
*reason = "wrong type for method " + m.Name()
|
||||
} else {
|
||||
*reason = "missing method " + m.Name()
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// x is a bidirectional channel value, T is a channel
|
||||
// type, x's type V and T have identical element types,
|
||||
// and at least one of V or T is not a named type
|
||||
if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
|
||||
if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
|
||||
return !isNamed(V) || !isNamed(T)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
123
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/ordering.go
generated
vendored
123
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/ordering.go
generated
vendored
@ -1,123 +0,0 @@
|
||||
// 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 resolveOrder.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// resolveOrder computes the order in which package-level objects
|
||||
// must be type-checked.
|
||||
//
|
||||
// Interface types appear first in the list, sorted topologically
|
||||
// by dependencies on embedded interfaces that are also declared
|
||||
// in this package, followed by all other objects sorted in source
|
||||
// order.
|
||||
//
|
||||
// TODO(gri) Consider sorting all types by dependencies here, and
|
||||
// in the process check _and_ report type cycles. This may simplify
|
||||
// the full type-checking phase.
|
||||
//
|
||||
func (check *Checker) resolveOrder() []Object {
|
||||
var ifaces, others []Object
|
||||
|
||||
// collect interface types with their dependencies, and all other objects
|
||||
for obj := range check.objMap {
|
||||
if ityp := check.interfaceFor(obj); ityp != nil {
|
||||
ifaces = append(ifaces, obj)
|
||||
// determine dependencies on embedded interfaces
|
||||
for _, f := range ityp.Methods.List {
|
||||
if len(f.Names) == 0 {
|
||||
// Embedded interface: The type must be a (possibly
|
||||
// qualified) identifier denoting another interface.
|
||||
// Imported interfaces are already fully resolved,
|
||||
// so we can ignore qualified identifiers.
|
||||
if ident, _ := f.Type.(*ast.Ident); ident != nil {
|
||||
embedded := check.pkg.scope.Lookup(ident.Name)
|
||||
if check.interfaceFor(embedded) != nil {
|
||||
check.objMap[obj].addDep(embedded)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
others = append(others, obj)
|
||||
}
|
||||
}
|
||||
|
||||
// final object order
|
||||
var order []Object
|
||||
|
||||
// sort interface types topologically by dependencies,
|
||||
// and in source order if there are no dependencies
|
||||
sort.Sort(inSourceOrder(ifaces))
|
||||
visited := make(objSet)
|
||||
for _, obj := range ifaces {
|
||||
check.appendInPostOrder(&order, obj, visited)
|
||||
}
|
||||
|
||||
// sort everything else in source order
|
||||
sort.Sort(inSourceOrder(others))
|
||||
|
||||
return append(order, others...)
|
||||
}
|
||||
|
||||
// interfaceFor returns the AST interface denoted by obj, or nil.
|
||||
func (check *Checker) interfaceFor(obj Object) *ast.InterfaceType {
|
||||
tname, _ := obj.(*TypeName)
|
||||
if tname == nil {
|
||||
return nil // not a type
|
||||
}
|
||||
d := check.objMap[obj]
|
||||
if d == nil {
|
||||
check.dump("%s: %s should have been declared", obj.Pos(), obj.Name())
|
||||
unreachable()
|
||||
}
|
||||
if d.typ == nil {
|
||||
return nil // invalid AST - ignore (will be handled later)
|
||||
}
|
||||
ityp, _ := d.typ.(*ast.InterfaceType)
|
||||
return ityp
|
||||
}
|
||||
|
||||
func (check *Checker) appendInPostOrder(order *[]Object, obj Object, visited objSet) {
|
||||
if visited[obj] {
|
||||
// We've already seen this object; either because it's
|
||||
// already added to order, or because we have a cycle.
|
||||
// In both cases we stop. Cycle errors are reported
|
||||
// when type-checking types.
|
||||
return
|
||||
}
|
||||
visited[obj] = true
|
||||
|
||||
d := check.objMap[obj]
|
||||
for _, obj := range orderedSetObjects(d.deps) {
|
||||
check.appendInPostOrder(order, obj, visited)
|
||||
}
|
||||
|
||||
*order = append(*order, obj)
|
||||
}
|
||||
|
||||
func orderedSetObjects(set objSet) []Object {
|
||||
list := make([]Object, len(set))
|
||||
i := 0
|
||||
for obj := range set {
|
||||
// we don't care about the map element value
|
||||
list[i] = obj
|
||||
i++
|
||||
}
|
||||
sort.Sort(inSourceOrder(list))
|
||||
return list
|
||||
}
|
||||
|
||||
// inSourceOrder implements the sort.Sort interface.
|
||||
type inSourceOrder []Object
|
||||
|
||||
func (a inSourceOrder) Len() int { return len(a) }
|
||||
func (a inSourceOrder) Less(i, j int) bool { return a[i].order() < a[j].order() }
|
||||
func (a inSourceOrder) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
64
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/package.go
generated
vendored
64
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/package.go
generated
vendored
@ -1,64 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// A Package describes a Go package.
|
||||
type Package struct {
|
||||
path string
|
||||
name string
|
||||
scope *Scope
|
||||
complete bool
|
||||
imports []*Package
|
||||
fake bool // scope lookup errors are silently dropped if package is fake (internal use only)
|
||||
}
|
||||
|
||||
// NewPackage returns a new Package for the given package path and name.
|
||||
// The package is not complete and contains no explicit imports.
|
||||
func NewPackage(path, name string) *Package {
|
||||
scope := NewScope(Universe, token.NoPos, token.NoPos, fmt.Sprintf("package %q", path))
|
||||
return &Package{path: path, name: name, scope: scope}
|
||||
}
|
||||
|
||||
// Path returns the package path.
|
||||
func (pkg *Package) Path() string { return pkg.path }
|
||||
|
||||
// Name returns the package name.
|
||||
func (pkg *Package) Name() string { return pkg.name }
|
||||
|
||||
// SetName sets the package name.
|
||||
func (pkg *Package) SetName(name string) { pkg.name = name }
|
||||
|
||||
// Scope returns the (complete or incomplete) package scope
|
||||
// holding the objects declared at package level (TypeNames,
|
||||
// Consts, Vars, and Funcs).
|
||||
func (pkg *Package) Scope() *Scope { return pkg.scope }
|
||||
|
||||
// A package is complete if its scope contains (at least) all
|
||||
// exported objects; otherwise it is incomplete.
|
||||
func (pkg *Package) Complete() bool { return pkg.complete }
|
||||
|
||||
// MarkComplete marks a package as complete.
|
||||
func (pkg *Package) MarkComplete() { pkg.complete = true }
|
||||
|
||||
// Imports returns the list of packages directly imported by
|
||||
// pkg; the list is in source order.
|
||||
//
|
||||
// If pkg was loaded from export data, Imports includes packages that
|
||||
// provide package-level objects referenced by pkg. This may be more or
|
||||
// less than the set of packages directly imported by pkg's source code.
|
||||
func (pkg *Package) Imports() []*Package { return pkg.imports }
|
||||
|
||||
// SetImports sets the list of explicitly imported packages to list.
|
||||
// It is the caller's responsibility to make sure list elements are unique.
|
||||
func (pkg *Package) SetImports(list []*Package) { pkg.imports = list }
|
||||
|
||||
func (pkg *Package) String() string {
|
||||
return fmt.Sprintf("package %s (%q)", pkg.name, pkg.path)
|
||||
}
|
320
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/predicates.go
generated
vendored
320
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/predicates.go
generated
vendored
@ -1,320 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements commonly used type predicates.
|
||||
|
||||
package types
|
||||
|
||||
import "sort"
|
||||
|
||||
func isNamed(typ Type) bool {
|
||||
if _, ok := typ.(*Basic); ok {
|
||||
return ok
|
||||
}
|
||||
_, ok := typ.(*Named)
|
||||
return ok
|
||||
}
|
||||
|
||||
func isBoolean(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.info&IsBoolean != 0
|
||||
}
|
||||
|
||||
func isInteger(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.info&IsInteger != 0
|
||||
}
|
||||
|
||||
func isUnsigned(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.info&IsUnsigned != 0
|
||||
}
|
||||
|
||||
func isFloat(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.info&IsFloat != 0
|
||||
}
|
||||
|
||||
func isComplex(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.info&IsComplex != 0
|
||||
}
|
||||
|
||||
func isNumeric(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.info&IsNumeric != 0
|
||||
}
|
||||
|
||||
func isString(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.info&IsString != 0
|
||||
}
|
||||
|
||||
func isTyped(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return !ok || t.info&IsUntyped == 0
|
||||
}
|
||||
|
||||
func isUntyped(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.info&IsUntyped != 0
|
||||
}
|
||||
|
||||
func isOrdered(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.info&IsOrdered != 0
|
||||
}
|
||||
|
||||
func isConstType(typ Type) bool {
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.info&IsConstType != 0
|
||||
}
|
||||
|
||||
// IsInterface reports whether typ is an interface type.
|
||||
func IsInterface(typ Type) bool {
|
||||
_, ok := typ.Underlying().(*Interface)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Comparable reports whether values of type T are comparable.
|
||||
func Comparable(T Type) bool {
|
||||
switch t := T.Underlying().(type) {
|
||||
case *Basic:
|
||||
// assume invalid types to be comparable
|
||||
// to avoid follow-up errors
|
||||
return t.kind != UntypedNil
|
||||
case *Pointer, *Interface, *Chan:
|
||||
return true
|
||||
case *Struct:
|
||||
for _, f := range t.fields {
|
||||
if !Comparable(f.typ) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case *Array:
|
||||
return Comparable(t.elem)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// hasNil reports whether a type includes the nil value.
|
||||
func hasNil(typ Type) bool {
|
||||
switch t := typ.Underlying().(type) {
|
||||
case *Basic:
|
||||
return t.kind == UnsafePointer
|
||||
case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Identical reports whether x and y are identical types.
|
||||
// Receivers of Signature types are ignored.
|
||||
func Identical(x, y Type) bool {
|
||||
return identical(x, y, true, nil)
|
||||
}
|
||||
|
||||
// IdenticalIgnoreTags reports whether x and y are identical types if tags are ignored.
|
||||
// Receivers of Signature types are ignored.
|
||||
func IdenticalIgnoreTags(x, y Type) bool {
|
||||
return identical(x, y, false, nil)
|
||||
}
|
||||
|
||||
// An ifacePair is a node in a stack of interface type pairs compared for identity.
|
||||
type ifacePair struct {
|
||||
x, y *Interface
|
||||
prev *ifacePair
|
||||
}
|
||||
|
||||
func (p *ifacePair) identical(q *ifacePair) bool {
|
||||
return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
|
||||
}
|
||||
|
||||
func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
|
||||
if x == y {
|
||||
return true
|
||||
}
|
||||
|
||||
switch x := x.(type) {
|
||||
case *Basic:
|
||||
// Basic types are singletons except for the rune and byte
|
||||
// aliases, thus we cannot solely rely on the x == y check
|
||||
// above. See also comment in TypeName.IsAlias.
|
||||
if y, ok := y.(*Basic); ok {
|
||||
return x.kind == y.kind
|
||||
}
|
||||
|
||||
case *Array:
|
||||
// Two array types are identical if they have identical element types
|
||||
// and the same array length.
|
||||
if y, ok := y.(*Array); ok {
|
||||
// If one or both array lengths are unknown (< 0) due to some error,
|
||||
// assume they are the same to avoid spurious follow-on errors.
|
||||
return (x.len < 0 || y.len < 0 || x.len == y.len) && identical(x.elem, y.elem, cmpTags, p)
|
||||
}
|
||||
|
||||
case *Slice:
|
||||
// Two slice types are identical if they have identical element types.
|
||||
if y, ok := y.(*Slice); ok {
|
||||
return identical(x.elem, y.elem, cmpTags, p)
|
||||
}
|
||||
|
||||
case *Struct:
|
||||
// Two struct types are identical if they have the same sequence of fields,
|
||||
// and if corresponding fields have the same names, and identical types,
|
||||
// and identical tags. Two anonymous fields are considered to have the same
|
||||
// name. Lower-case field names from different packages are always different.
|
||||
if y, ok := y.(*Struct); ok {
|
||||
if x.NumFields() == y.NumFields() {
|
||||
for i, f := range x.fields {
|
||||
g := y.fields[i]
|
||||
if f.anonymous != g.anonymous ||
|
||||
cmpTags && x.Tag(i) != y.Tag(i) ||
|
||||
!f.sameId(g.pkg, g.name) ||
|
||||
!identical(f.typ, g.typ, cmpTags, p) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case *Pointer:
|
||||
// Two pointer types are identical if they have identical base types.
|
||||
if y, ok := y.(*Pointer); ok {
|
||||
return identical(x.base, y.base, cmpTags, p)
|
||||
}
|
||||
|
||||
case *Tuple:
|
||||
// Two tuples types are identical if they have the same number of elements
|
||||
// and corresponding elements have identical types.
|
||||
if y, ok := y.(*Tuple); ok {
|
||||
if x.Len() == y.Len() {
|
||||
if x != nil {
|
||||
for i, v := range x.vars {
|
||||
w := y.vars[i]
|
||||
if !identical(v.typ, w.typ, cmpTags, p) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case *Signature:
|
||||
// Two function types are identical if they have the same number of parameters
|
||||
// and result values, corresponding parameter and result types are identical,
|
||||
// and either both functions are variadic or neither is. Parameter and result
|
||||
// names are not required to match.
|
||||
if y, ok := y.(*Signature); ok {
|
||||
return x.variadic == y.variadic &&
|
||||
identical(x.params, y.params, cmpTags, p) &&
|
||||
identical(x.results, y.results, cmpTags, p)
|
||||
}
|
||||
|
||||
case *Interface:
|
||||
// Two interface types are identical if they have the same set of methods with
|
||||
// the same names and identical function types. Lower-case method names from
|
||||
// different packages are always different. The order of the methods is irrelevant.
|
||||
if y, ok := y.(*Interface); ok {
|
||||
a := x.allMethods
|
||||
b := y.allMethods
|
||||
if len(a) == len(b) {
|
||||
// Interface types are the only types where cycles can occur
|
||||
// that are not "terminated" via named types; and such cycles
|
||||
// can only be created via method parameter types that are
|
||||
// anonymous interfaces (directly or indirectly) embedding
|
||||
// the current interface. Example:
|
||||
//
|
||||
// type T interface {
|
||||
// m() interface{T}
|
||||
// }
|
||||
//
|
||||
// If two such (differently named) interfaces are compared,
|
||||
// endless recursion occurs if the cycle is not detected.
|
||||
//
|
||||
// If x and y were compared before, they must be equal
|
||||
// (if they were not, the recursion would have stopped);
|
||||
// search the ifacePair stack for the same pair.
|
||||
//
|
||||
// This is a quadratic algorithm, but in practice these stacks
|
||||
// are extremely short (bounded by the nesting depth of interface
|
||||
// type declarations that recur via parameter types, an extremely
|
||||
// rare occurrence). An alternative implementation might use a
|
||||
// "visited" map, but that is probably less efficient overall.
|
||||
q := &ifacePair{x, y, p}
|
||||
for p != nil {
|
||||
if p.identical(q) {
|
||||
return true // same pair was compared before
|
||||
}
|
||||
p = p.prev
|
||||
}
|
||||
if debug {
|
||||
assert(sort.IsSorted(byUniqueMethodName(a)))
|
||||
assert(sort.IsSorted(byUniqueMethodName(b)))
|
||||
}
|
||||
for i, f := range a {
|
||||
g := b[i]
|
||||
if f.Id() != g.Id() || !identical(f.typ, g.typ, cmpTags, q) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case *Map:
|
||||
// Two map types are identical if they have identical key and value types.
|
||||
if y, ok := y.(*Map); ok {
|
||||
return identical(x.key, y.key, cmpTags, p) && identical(x.elem, y.elem, cmpTags, p)
|
||||
}
|
||||
|
||||
case *Chan:
|
||||
// Two channel types are identical if they have identical value types
|
||||
// and the same direction.
|
||||
if y, ok := y.(*Chan); ok {
|
||||
return x.dir == y.dir && identical(x.elem, y.elem, cmpTags, p)
|
||||
}
|
||||
|
||||
case *Named:
|
||||
// Two named types are identical if their type names originate
|
||||
// in the same type declaration.
|
||||
if y, ok := y.(*Named); ok {
|
||||
return x.obj == y.obj
|
||||
}
|
||||
|
||||
case nil:
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Default returns the default "typed" type for an "untyped" type;
|
||||
// it returns the incoming type for all other types. The default type
|
||||
// for untyped nil is untyped nil.
|
||||
//
|
||||
func Default(typ Type) Type {
|
||||
if t, ok := typ.(*Basic); ok {
|
||||
switch t.kind {
|
||||
case UntypedBool:
|
||||
return Typ[Bool]
|
||||
case UntypedInt:
|
||||
return Typ[Int]
|
||||
case UntypedRune:
|
||||
return universeRune // use 'rune' name
|
||||
case UntypedFloat:
|
||||
return Typ[Float64]
|
||||
case UntypedComplex:
|
||||
return Typ[Complex128]
|
||||
case UntypedString:
|
||||
return Typ[String]
|
||||
}
|
||||
}
|
||||
return typ
|
||||
}
|
542
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/resolver.go
generated
vendored
542
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/resolver.go
generated
vendored
@ -1,542 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// A declInfo describes a package-level const, type, var, or func declaration.
|
||||
type declInfo struct {
|
||||
file *Scope // scope of file containing this declaration
|
||||
lhs []*Var // lhs of n:1 variable declarations, or nil
|
||||
typ ast.Expr // type, or nil
|
||||
init ast.Expr // init/orig expression, or nil
|
||||
fdecl *ast.FuncDecl // func declaration, or nil
|
||||
alias bool // type alias declaration
|
||||
|
||||
// The deps field tracks initialization expression dependencies.
|
||||
// As a special (overloaded) case, it also tracks dependencies of
|
||||
// interface types on embedded interfaces (see ordering.go).
|
||||
deps objSet // lazily initialized
|
||||
}
|
||||
|
||||
// An objSet is simply a set of objects.
|
||||
type objSet map[Object]bool
|
||||
|
||||
// hasInitializer reports whether the declared object has an initialization
|
||||
// expression or function body.
|
||||
func (d *declInfo) hasInitializer() bool {
|
||||
return d.init != nil || d.fdecl != nil && d.fdecl.Body != nil
|
||||
}
|
||||
|
||||
// addDep adds obj to the set of objects d's init expression depends on.
|
||||
func (d *declInfo) addDep(obj Object) {
|
||||
m := d.deps
|
||||
if m == nil {
|
||||
m = make(objSet)
|
||||
d.deps = m
|
||||
}
|
||||
m[obj] = true
|
||||
}
|
||||
|
||||
// arityMatch checks that the lhs and rhs of a const or var decl
|
||||
// have the appropriate number of names and init exprs. For const
|
||||
// decls, init is the value spec providing the init exprs; for
|
||||
// var decls, init is nil (the init exprs are in s in this case).
|
||||
func (check *Checker) arityMatch(s, init *ast.ValueSpec) {
|
||||
l := len(s.Names)
|
||||
r := len(s.Values)
|
||||
if init != nil {
|
||||
r = len(init.Values)
|
||||
}
|
||||
|
||||
switch {
|
||||
case init == nil && r == 0:
|
||||
// var decl w/o init expr
|
||||
if s.Type == nil {
|
||||
check.errorf(s.Pos(), "missing type or init expr")
|
||||
}
|
||||
case l < r:
|
||||
if l < len(s.Values) {
|
||||
// init exprs from s
|
||||
n := s.Values[l]
|
||||
check.errorf(n.Pos(), "extra init expr %s", n)
|
||||
// TODO(gri) avoid declared but not used error here
|
||||
} else {
|
||||
// init exprs "inherited"
|
||||
check.errorf(s.Pos(), "extra init expr at %s", check.fset.Position(init.Pos()))
|
||||
// TODO(gri) avoid declared but not used error here
|
||||
}
|
||||
case l > r && (init != nil || r != 1):
|
||||
n := s.Names[r]
|
||||
check.errorf(n.Pos(), "missing init expr for %s", n)
|
||||
}
|
||||
}
|
||||
|
||||
func validatedImportPath(path string) (string, error) {
|
||||
s, err := strconv.Unquote(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if s == "" {
|
||||
return "", fmt.Errorf("empty string")
|
||||
}
|
||||
const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
|
||||
for _, r := range s {
|
||||
if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
|
||||
return s, fmt.Errorf("invalid character %#U", r)
|
||||
}
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// declarePkgObj declares obj in the package scope, records its ident -> obj mapping,
|
||||
// and updates check.objMap. The object must not be a function or method.
|
||||
func (check *Checker) declarePkgObj(ident *ast.Ident, obj Object, d *declInfo) {
|
||||
assert(ident.Name == obj.Name())
|
||||
|
||||
// spec: "A package-scope or file-scope identifier with name init
|
||||
// may only be declared to be a function with this (func()) signature."
|
||||
if ident.Name == "init" {
|
||||
check.errorf(ident.Pos(), "cannot declare init - must be func")
|
||||
return
|
||||
}
|
||||
|
||||
// spec: "The main package must have package name main and declare
|
||||
// a function main that takes no arguments and returns no value."
|
||||
if ident.Name == "main" && check.pkg.name == "main" {
|
||||
check.errorf(ident.Pos(), "cannot declare main - must be func")
|
||||
return
|
||||
}
|
||||
|
||||
check.declare(check.pkg.scope, ident, obj, token.NoPos)
|
||||
check.objMap[obj] = d
|
||||
obj.setOrder(uint32(len(check.objMap)))
|
||||
}
|
||||
|
||||
// filename returns a filename suitable for debugging output.
|
||||
func (check *Checker) filename(fileNo int) string {
|
||||
file := check.files[fileNo]
|
||||
if pos := file.Pos(); pos.IsValid() {
|
||||
return check.fset.File(pos).Name()
|
||||
}
|
||||
return fmt.Sprintf("file[%d]", fileNo)
|
||||
}
|
||||
|
||||
func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package {
|
||||
// If we already have a package for the given (path, dir)
|
||||
// pair, use it instead of doing a full import.
|
||||
// Checker.impMap only caches packages that are marked Complete
|
||||
// or fake (dummy packages for failed imports). Incomplete but
|
||||
// non-fake packages do require an import to complete them.
|
||||
key := importKey{path, dir}
|
||||
imp := check.impMap[key]
|
||||
if imp != nil {
|
||||
return imp
|
||||
}
|
||||
|
||||
// no package yet => import it
|
||||
if path == "C" && check.conf.FakeImportC {
|
||||
imp = NewPackage("C", "C")
|
||||
imp.fake = true
|
||||
} else {
|
||||
// ordinary import
|
||||
var err error
|
||||
if importer := check.conf.Importer; importer == nil {
|
||||
err = fmt.Errorf("Config.Importer not installed")
|
||||
} else if importerFrom, ok := importer.(ImporterFrom); ok {
|
||||
imp, err = importerFrom.ImportFrom(path, dir, 0)
|
||||
if imp == nil && err == nil {
|
||||
err = fmt.Errorf("Config.Importer.ImportFrom(%s, %s, 0) returned nil but no error", path, dir)
|
||||
}
|
||||
} else {
|
||||
imp, err = importer.Import(path)
|
||||
if imp == nil && err == nil {
|
||||
err = fmt.Errorf("Config.Importer.Import(%s) returned nil but no error", path)
|
||||
}
|
||||
}
|
||||
// make sure we have a valid package name
|
||||
// (errors here can only happen through manipulation of packages after creation)
|
||||
if err == nil && imp != nil && (imp.name == "_" || imp.name == "") {
|
||||
err = fmt.Errorf("invalid package name: %q", imp.name)
|
||||
imp = nil // create fake package below
|
||||
}
|
||||
if err != nil {
|
||||
check.errorf(pos, "could not import %s (%s)", path, err)
|
||||
if imp == nil {
|
||||
// create a new fake package
|
||||
// come up with a sensible package name (heuristic)
|
||||
name := path
|
||||
if i := len(name); i > 0 && name[i-1] == '/' {
|
||||
name = name[:i-1]
|
||||
}
|
||||
if i := strings.LastIndex(name, "/"); i >= 0 {
|
||||
name = name[i+1:]
|
||||
}
|
||||
imp = NewPackage(path, name)
|
||||
}
|
||||
// continue to use the package as best as we can
|
||||
imp.fake = true // avoid follow-up lookup failures
|
||||
}
|
||||
}
|
||||
|
||||
// package should be complete or marked fake, but be cautious
|
||||
if imp.complete || imp.fake {
|
||||
check.impMap[key] = imp
|
||||
return imp
|
||||
}
|
||||
|
||||
// something went wrong (importer may have returned incomplete package without error)
|
||||
return nil
|
||||
}
|
||||
|
||||
// collectObjects collects all file and package objects and inserts them
|
||||
// into their respective scopes. It also performs imports and associates
|
||||
// methods with receiver base type names.
|
||||
func (check *Checker) collectObjects() {
|
||||
pkg := check.pkg
|
||||
|
||||
// pkgImports is the set of packages already imported by any package file seen
|
||||
// so far. Used to avoid duplicate entries in pkg.imports. Allocate and populate
|
||||
// it (pkg.imports may not be empty if we are checking test files incrementally).
|
||||
// Note that pkgImports is keyed by package (and thus package path), not by an
|
||||
// importKey value. Two different importKey values may map to the same package
|
||||
// which is why we cannot use the check.impMap here.
|
||||
var pkgImports = make(map[*Package]bool)
|
||||
for _, imp := range pkg.imports {
|
||||
pkgImports[imp] = true
|
||||
}
|
||||
|
||||
for fileNo, file := range check.files {
|
||||
// The package identifier denotes the current package,
|
||||
// but there is no corresponding package object.
|
||||
check.recordDef(file.Name, nil)
|
||||
|
||||
// Use the actual source file extent rather than *ast.File extent since the
|
||||
// latter doesn't include comments which appear at the start or end of the file.
|
||||
// Be conservative and use the *ast.File extent if we don't have a *token.File.
|
||||
pos, end := file.Pos(), file.End()
|
||||
if f := check.fset.File(file.Pos()); f != nil {
|
||||
pos, end = token.Pos(f.Base()), token.Pos(f.Base()+f.Size())
|
||||
}
|
||||
fileScope := NewScope(check.pkg.scope, pos, end, check.filename(fileNo))
|
||||
check.recordScope(file, fileScope)
|
||||
|
||||
// determine file directory, necessary to resolve imports
|
||||
// FileName may be "" (typically for tests) in which case
|
||||
// we get "." as the directory which is what we would want.
|
||||
fileDir := dir(check.fset.Position(file.Name.Pos()).Filename)
|
||||
|
||||
for _, decl := range file.Decls {
|
||||
switch d := decl.(type) {
|
||||
case *ast.BadDecl:
|
||||
// ignore
|
||||
|
||||
case *ast.GenDecl:
|
||||
var last *ast.ValueSpec // last ValueSpec with type or init exprs seen
|
||||
for iota, spec := range d.Specs {
|
||||
switch s := spec.(type) {
|
||||
case *ast.ImportSpec:
|
||||
// import package
|
||||
path, err := validatedImportPath(s.Path.Value)
|
||||
if err != nil {
|
||||
check.errorf(s.Path.Pos(), "invalid import path (%s)", err)
|
||||
continue
|
||||
}
|
||||
|
||||
imp := check.importPackage(s.Path.Pos(), path, fileDir)
|
||||
if imp == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// add package to list of explicit imports
|
||||
// (this functionality is provided as a convenience
|
||||
// for clients; it is not needed for type-checking)
|
||||
if !pkgImports[imp] {
|
||||
pkgImports[imp] = true
|
||||
pkg.imports = append(pkg.imports, imp)
|
||||
}
|
||||
|
||||
// local name overrides imported package name
|
||||
name := imp.name
|
||||
if s.Name != nil {
|
||||
name = s.Name.Name
|
||||
if path == "C" {
|
||||
// match cmd/compile (not prescribed by spec)
|
||||
check.errorf(s.Name.Pos(), `cannot rename import "C"`)
|
||||
continue
|
||||
}
|
||||
if name == "init" {
|
||||
check.errorf(s.Name.Pos(), "cannot declare init - must be func")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
obj := NewPkgName(s.Pos(), pkg, name, imp)
|
||||
if s.Name != nil {
|
||||
// in a dot-import, the dot represents the package
|
||||
check.recordDef(s.Name, obj)
|
||||
} else {
|
||||
check.recordImplicit(s, obj)
|
||||
}
|
||||
|
||||
if path == "C" {
|
||||
// match cmd/compile (not prescribed by spec)
|
||||
obj.used = true
|
||||
}
|
||||
|
||||
// add import to file scope
|
||||
if name == "." {
|
||||
// merge imported scope with file scope
|
||||
for _, obj := range imp.scope.elems {
|
||||
// A package scope may contain non-exported objects,
|
||||
// do not import them!
|
||||
if obj.Exported() {
|
||||
// TODO(gri) When we import a package, we create
|
||||
// a new local package object. We should do the
|
||||
// same for each dot-imported object. That way
|
||||
// they can have correct position information.
|
||||
// (We must not modify their existing position
|
||||
// information because the same package - found
|
||||
// via Config.Packages - may be dot-imported in
|
||||
// another package!)
|
||||
check.declare(fileScope, nil, obj, token.NoPos)
|
||||
}
|
||||
}
|
||||
// add position to set of dot-import positions for this file
|
||||
// (this is only needed for "imported but not used" errors)
|
||||
check.addUnusedDotImport(fileScope, imp, s.Pos())
|
||||
} else {
|
||||
// declare imported package object in file scope
|
||||
check.declare(fileScope, nil, obj, token.NoPos)
|
||||
}
|
||||
|
||||
case *ast.ValueSpec:
|
||||
switch d.Tok {
|
||||
case token.CONST:
|
||||
// determine which initialization expressions to use
|
||||
switch {
|
||||
case s.Type != nil || len(s.Values) > 0:
|
||||
last = s
|
||||
case last == nil:
|
||||
last = new(ast.ValueSpec) // make sure last exists
|
||||
}
|
||||
|
||||
// declare all constants
|
||||
for i, name := range s.Names {
|
||||
obj := NewConst(name.Pos(), pkg, name.Name, nil, constant.MakeInt64(int64(iota)))
|
||||
|
||||
var init ast.Expr
|
||||
if i < len(last.Values) {
|
||||
init = last.Values[i]
|
||||
}
|
||||
|
||||
d := &declInfo{file: fileScope, typ: last.Type, init: init}
|
||||
check.declarePkgObj(name, obj, d)
|
||||
}
|
||||
|
||||
check.arityMatch(s, last)
|
||||
|
||||
case token.VAR:
|
||||
lhs := make([]*Var, len(s.Names))
|
||||
// If there's exactly one rhs initializer, use
|
||||
// the same declInfo d1 for all lhs variables
|
||||
// so that each lhs variable depends on the same
|
||||
// rhs initializer (n:1 var declaration).
|
||||
var d1 *declInfo
|
||||
if len(s.Values) == 1 {
|
||||
// The lhs elements are only set up after the for loop below,
|
||||
// but that's ok because declareVar only collects the declInfo
|
||||
// for a later phase.
|
||||
d1 = &declInfo{file: fileScope, lhs: lhs, typ: s.Type, init: s.Values[0]}
|
||||
}
|
||||
|
||||
// declare all variables
|
||||
for i, name := range s.Names {
|
||||
obj := NewVar(name.Pos(), pkg, name.Name, nil)
|
||||
lhs[i] = obj
|
||||
|
||||
d := d1
|
||||
if d == nil {
|
||||
// individual assignments
|
||||
var init ast.Expr
|
||||
if i < len(s.Values) {
|
||||
init = s.Values[i]
|
||||
}
|
||||
d = &declInfo{file: fileScope, typ: s.Type, init: init}
|
||||
}
|
||||
|
||||
check.declarePkgObj(name, obj, d)
|
||||
}
|
||||
|
||||
check.arityMatch(s, nil)
|
||||
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "invalid token %s", d.Tok)
|
||||
}
|
||||
|
||||
case *ast.TypeSpec:
|
||||
obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil)
|
||||
check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, typ: s.Type, alias: s.Assign.IsValid()})
|
||||
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s)
|
||||
}
|
||||
}
|
||||
|
||||
case *ast.FuncDecl:
|
||||
name := d.Name.Name
|
||||
obj := NewFunc(d.Name.Pos(), pkg, name, nil)
|
||||
if d.Recv == nil {
|
||||
// regular function
|
||||
if name == "init" {
|
||||
// don't declare init functions in the package scope - they are invisible
|
||||
obj.parent = pkg.scope
|
||||
check.recordDef(d.Name, obj)
|
||||
// init functions must have a body
|
||||
if d.Body == nil {
|
||||
check.softErrorf(obj.pos, "missing function body")
|
||||
}
|
||||
} else {
|
||||
check.declare(pkg.scope, d.Name, obj, token.NoPos)
|
||||
}
|
||||
} else {
|
||||
// method
|
||||
check.recordDef(d.Name, obj)
|
||||
// Associate method with receiver base type name, if possible.
|
||||
// Ignore methods that have an invalid receiver, or a blank _
|
||||
// receiver name. They will be type-checked later, with regular
|
||||
// functions.
|
||||
if list := d.Recv.List; len(list) > 0 {
|
||||
typ := unparen(list[0].Type)
|
||||
if ptr, _ := typ.(*ast.StarExpr); ptr != nil {
|
||||
typ = unparen(ptr.X)
|
||||
}
|
||||
if base, _ := typ.(*ast.Ident); base != nil && base.Name != "_" {
|
||||
check.assocMethod(base.Name, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
info := &declInfo{file: fileScope, fdecl: d}
|
||||
check.objMap[obj] = info
|
||||
obj.setOrder(uint32(len(check.objMap)))
|
||||
|
||||
default:
|
||||
check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// verify that objects in package and file scopes have different names
|
||||
for _, scope := range check.pkg.scope.children /* file scopes */ {
|
||||
for _, obj := range scope.elems {
|
||||
if alt := pkg.scope.Lookup(obj.Name()); alt != nil {
|
||||
if pkg, ok := obj.(*PkgName); ok {
|
||||
check.errorf(alt.Pos(), "%s already declared through import of %s", alt.Name(), pkg.Imported())
|
||||
check.reportAltDecl(pkg)
|
||||
} else {
|
||||
check.errorf(alt.Pos(), "%s already declared through dot-import of %s", alt.Name(), obj.Pkg())
|
||||
// TODO(gri) dot-imported objects don't have a position; reportAltDecl won't print anything
|
||||
check.reportAltDecl(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// packageObjects typechecks all package objects in objList, but not function bodies.
|
||||
func (check *Checker) packageObjects(objList []Object) {
|
||||
// add new methods to already type-checked types (from a prior Checker.Files call)
|
||||
for _, obj := range objList {
|
||||
if obj, _ := obj.(*TypeName); obj != nil && obj.typ != nil {
|
||||
check.addMethodDecls(obj)
|
||||
}
|
||||
}
|
||||
|
||||
// pre-allocate space for type declaration paths so that the underlying array is reused
|
||||
typePath := make([]*TypeName, 0, 8)
|
||||
|
||||
for _, obj := range objList {
|
||||
check.objDecl(obj, nil, typePath)
|
||||
}
|
||||
|
||||
// At this point we may have a non-empty check.methods map; this means that not all
|
||||
// entries were deleted at the end of typeDecl because the respective receiver base
|
||||
// types were not found. In that case, an error was reported when declaring those
|
||||
// methods. We can now safely discard this map.
|
||||
check.methods = nil
|
||||
}
|
||||
|
||||
// functionBodies typechecks all function bodies.
|
||||
func (check *Checker) functionBodies() {
|
||||
for _, f := range check.funcs {
|
||||
check.funcBody(f.decl, f.name, f.sig, f.body)
|
||||
}
|
||||
}
|
||||
|
||||
// unusedImports checks for unused imports.
|
||||
func (check *Checker) unusedImports() {
|
||||
// if function bodies are not checked, packages' uses are likely missing - don't check
|
||||
if check.conf.IgnoreFuncBodies {
|
||||
return
|
||||
}
|
||||
|
||||
// spec: "It is illegal (...) to directly import a package without referring to
|
||||
// any of its exported identifiers. To import a package solely for its side-effects
|
||||
// (initialization), use the blank identifier as explicit package name."
|
||||
|
||||
// check use of regular imported packages
|
||||
for _, scope := range check.pkg.scope.children /* file scopes */ {
|
||||
for _, obj := range scope.elems {
|
||||
if obj, ok := obj.(*PkgName); ok {
|
||||
// Unused "blank imports" are automatically ignored
|
||||
// since _ identifiers are not entered into scopes.
|
||||
if !obj.used {
|
||||
path := obj.imported.path
|
||||
base := pkgName(path)
|
||||
if obj.name == base {
|
||||
check.softErrorf(obj.pos, "%q imported but not used", path)
|
||||
} else {
|
||||
check.softErrorf(obj.pos, "%q imported but not used as %s", path, obj.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check use of dot-imported packages
|
||||
for _, unusedDotImports := range check.unusedDotImports {
|
||||
for pkg, pos := range unusedDotImports {
|
||||
check.softErrorf(pos, "%q imported but not used", pkg.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pkgName returns the package name (last element) of an import path.
|
||||
func pkgName(path string) string {
|
||||
if i := strings.LastIndex(path, "/"); i >= 0 {
|
||||
path = path[i+1:]
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// dir makes a good-faith attempt to return the directory
|
||||
// portion of path. If path is empty, the result is ".".
|
||||
// (Per the go/build package dependency tests, we cannot import
|
||||
// path/filepath and simply use filepath.Dir.)
|
||||
func dir(path string) string {
|
||||
if i := strings.LastIndexAny(path, `/\`); i > 0 {
|
||||
return path[:i]
|
||||
}
|
||||
// i <= 0
|
||||
return "."
|
||||
}
|
190
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/return.go
generated
vendored
190
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/return.go
generated
vendored
@ -1,190 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements isTerminating.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// isTerminating reports if s is a terminating statement.
|
||||
// If s is labeled, label is the label name; otherwise s
|
||||
// is "".
|
||||
func (check *Checker) isTerminating(s ast.Stmt, label string) bool {
|
||||
switch s := s.(type) {
|
||||
default:
|
||||
unreachable()
|
||||
|
||||
case *ast.BadStmt, *ast.DeclStmt, *ast.EmptyStmt, *ast.SendStmt,
|
||||
*ast.IncDecStmt, *ast.AssignStmt, *ast.GoStmt, *ast.DeferStmt,
|
||||
*ast.RangeStmt:
|
||||
// no chance
|
||||
|
||||
case *ast.LabeledStmt:
|
||||
return check.isTerminating(s.Stmt, s.Label.Name)
|
||||
|
||||
case *ast.ExprStmt:
|
||||
// the predeclared (possibly parenthesized) panic() function is terminating
|
||||
if call, _ := unparen(s.X).(*ast.CallExpr); call != nil {
|
||||
if id, _ := call.Fun.(*ast.Ident); id != nil {
|
||||
if _, obj := check.scope.LookupParent(id.Name, token.NoPos); obj != nil {
|
||||
if b, _ := obj.(*Builtin); b != nil && b.id == _Panic {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case *ast.ReturnStmt:
|
||||
return true
|
||||
|
||||
case *ast.BranchStmt:
|
||||
if s.Tok == token.GOTO || s.Tok == token.FALLTHROUGH {
|
||||
return true
|
||||
}
|
||||
|
||||
case *ast.BlockStmt:
|
||||
return check.isTerminatingList(s.List, "")
|
||||
|
||||
case *ast.IfStmt:
|
||||
if s.Else != nil &&
|
||||
check.isTerminating(s.Body, "") &&
|
||||
check.isTerminating(s.Else, "") {
|
||||
return true
|
||||
}
|
||||
|
||||
case *ast.SwitchStmt:
|
||||
return check.isTerminatingSwitch(s.Body, label)
|
||||
|
||||
case *ast.TypeSwitchStmt:
|
||||
return check.isTerminatingSwitch(s.Body, label)
|
||||
|
||||
case *ast.SelectStmt:
|
||||
for _, s := range s.Body.List {
|
||||
cc := s.(*ast.CommClause)
|
||||
if !check.isTerminatingList(cc.Body, "") || hasBreakList(cc.Body, label, true) {
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
return true
|
||||
|
||||
case *ast.ForStmt:
|
||||
if s.Cond == nil && !hasBreak(s.Body, label, true) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (check *Checker) isTerminatingList(list []ast.Stmt, label string) bool {
|
||||
// trailing empty statements are permitted - skip them
|
||||
for i := len(list) - 1; i >= 0; i-- {
|
||||
if _, ok := list[i].(*ast.EmptyStmt); !ok {
|
||||
return check.isTerminating(list[i], label)
|
||||
}
|
||||
}
|
||||
return false // all statements are empty
|
||||
}
|
||||
|
||||
func (check *Checker) isTerminatingSwitch(body *ast.BlockStmt, label string) bool {
|
||||
hasDefault := false
|
||||
for _, s := range body.List {
|
||||
cc := s.(*ast.CaseClause)
|
||||
if cc.List == nil {
|
||||
hasDefault = true
|
||||
}
|
||||
if !check.isTerminatingList(cc.Body, "") || hasBreakList(cc.Body, label, true) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return hasDefault
|
||||
}
|
||||
|
||||
// TODO(gri) For nested breakable statements, the current implementation of hasBreak
|
||||
// will traverse the same subtree repeatedly, once for each label. Replace
|
||||
// with a single-pass label/break matching phase.
|
||||
|
||||
// hasBreak reports if s is or contains a break statement
|
||||
// referring to the label-ed statement or implicit-ly the
|
||||
// closest outer breakable statement.
|
||||
func hasBreak(s ast.Stmt, label string, implicit bool) bool {
|
||||
switch s := s.(type) {
|
||||
default:
|
||||
unreachable()
|
||||
|
||||
case *ast.BadStmt, *ast.DeclStmt, *ast.EmptyStmt, *ast.ExprStmt,
|
||||
*ast.SendStmt, *ast.IncDecStmt, *ast.AssignStmt, *ast.GoStmt,
|
||||
*ast.DeferStmt, *ast.ReturnStmt:
|
||||
// no chance
|
||||
|
||||
case *ast.LabeledStmt:
|
||||
return hasBreak(s.Stmt, label, implicit)
|
||||
|
||||
case *ast.BranchStmt:
|
||||
if s.Tok == token.BREAK {
|
||||
if s.Label == nil {
|
||||
return implicit
|
||||
}
|
||||
if s.Label.Name == label {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case *ast.BlockStmt:
|
||||
return hasBreakList(s.List, label, implicit)
|
||||
|
||||
case *ast.IfStmt:
|
||||
if hasBreak(s.Body, label, implicit) ||
|
||||
s.Else != nil && hasBreak(s.Else, label, implicit) {
|
||||
return true
|
||||
}
|
||||
|
||||
case *ast.CaseClause:
|
||||
return hasBreakList(s.Body, label, implicit)
|
||||
|
||||
case *ast.SwitchStmt:
|
||||
if label != "" && hasBreak(s.Body, label, false) {
|
||||
return true
|
||||
}
|
||||
|
||||
case *ast.TypeSwitchStmt:
|
||||
if label != "" && hasBreak(s.Body, label, false) {
|
||||
return true
|
||||
}
|
||||
|
||||
case *ast.CommClause:
|
||||
return hasBreakList(s.Body, label, implicit)
|
||||
|
||||
case *ast.SelectStmt:
|
||||
if label != "" && hasBreak(s.Body, label, false) {
|
||||
return true
|
||||
}
|
||||
|
||||
case *ast.ForStmt:
|
||||
if label != "" && hasBreak(s.Body, label, false) {
|
||||
return true
|
||||
}
|
||||
|
||||
case *ast.RangeStmt:
|
||||
if label != "" && hasBreak(s.Body, label, false) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func hasBreakList(list []ast.Stmt, label string, implicit bool) bool {
|
||||
for _, s := range list {
|
||||
if hasBreak(s, label, implicit) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
191
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/scope.go
generated
vendored
191
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/scope.go
generated
vendored
@ -1,191 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements Scopes.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TODO(gri) Provide scopes with a name or other mechanism so that
|
||||
// objects can use that information for better printing.
|
||||
|
||||
// A Scope maintains a set of objects and links to its containing
|
||||
// (parent) and contained (children) scopes. Objects may be inserted
|
||||
// and looked up by name. The zero value for Scope is a ready-to-use
|
||||
// empty scope.
|
||||
type Scope struct {
|
||||
parent *Scope
|
||||
children []*Scope
|
||||
elems map[string]Object // lazily allocated
|
||||
pos, end token.Pos // scope extent; may be invalid
|
||||
comment string // for debugging only
|
||||
isFunc bool // set if this is a function scope (internal use only)
|
||||
}
|
||||
|
||||
// NewScope returns a new, empty scope contained in the given parent
|
||||
// scope, if any. The comment is for debugging only.
|
||||
func NewScope(parent *Scope, pos, end token.Pos, comment string) *Scope {
|
||||
s := &Scope{parent, nil, nil, pos, end, comment, false}
|
||||
// don't add children to Universe scope!
|
||||
if parent != nil && parent != Universe {
|
||||
parent.children = append(parent.children, s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Parent returns the scope's containing (parent) scope.
|
||||
func (s *Scope) Parent() *Scope { return s.parent }
|
||||
|
||||
// Len() returns the number of scope elements.
|
||||
func (s *Scope) Len() int { return len(s.elems) }
|
||||
|
||||
// Names returns the scope's element names in sorted order.
|
||||
func (s *Scope) Names() []string {
|
||||
names := make([]string, len(s.elems))
|
||||
i := 0
|
||||
for name := range s.elems {
|
||||
names[i] = name
|
||||
i++
|
||||
}
|
||||
sort.Strings(names)
|
||||
return names
|
||||
}
|
||||
|
||||
// NumChildren() returns the number of scopes nested in s.
|
||||
func (s *Scope) NumChildren() int { return len(s.children) }
|
||||
|
||||
// Child returns the i'th child scope for 0 <= i < NumChildren().
|
||||
func (s *Scope) Child(i int) *Scope { return s.children[i] }
|
||||
|
||||
// Lookup returns the object in scope s with the given name if such an
|
||||
// object exists; otherwise the result is nil.
|
||||
func (s *Scope) Lookup(name string) Object {
|
||||
return s.elems[name]
|
||||
}
|
||||
|
||||
// LookupParent follows the parent chain of scopes starting with s until
|
||||
// it finds a scope where Lookup(name) returns a non-nil object, and then
|
||||
// returns that scope and object. If a valid position pos is provided,
|
||||
// only objects that were declared at or before pos are considered.
|
||||
// If no such scope and object exists, the result is (nil, nil).
|
||||
//
|
||||
// Note that obj.Parent() may be different from the returned scope if the
|
||||
// object was inserted into the scope and already had a parent at that
|
||||
// time (see Insert, below). This can only happen for dot-imported objects
|
||||
// whose scope is the scope of the package that exported them.
|
||||
func (s *Scope) LookupParent(name string, pos token.Pos) (*Scope, Object) {
|
||||
for ; s != nil; s = s.parent {
|
||||
if obj := s.elems[name]; obj != nil && (!pos.IsValid() || obj.scopePos() <= pos) {
|
||||
return s, obj
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Insert attempts to insert an object obj into scope s.
|
||||
// If s already contains an alternative object alt with
|
||||
// the same name, Insert leaves s unchanged and returns alt.
|
||||
// Otherwise it inserts obj, sets the object's parent scope
|
||||
// if not already set, and returns nil.
|
||||
func (s *Scope) Insert(obj Object) Object {
|
||||
name := obj.Name()
|
||||
if alt := s.elems[name]; alt != nil {
|
||||
return alt
|
||||
}
|
||||
if s.elems == nil {
|
||||
s.elems = make(map[string]Object)
|
||||
}
|
||||
s.elems[name] = obj
|
||||
if obj.Parent() == nil {
|
||||
obj.setParent(s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Pos and End describe the scope's source code extent [pos, end).
|
||||
// The results are guaranteed to be valid only if the type-checked
|
||||
// AST has complete position information. The extent is undefined
|
||||
// for Universe and package scopes.
|
||||
func (s *Scope) Pos() token.Pos { return s.pos }
|
||||
func (s *Scope) End() token.Pos { return s.end }
|
||||
|
||||
// Contains returns true if pos is within the scope's extent.
|
||||
// The result is guaranteed to be valid only if the type-checked
|
||||
// AST has complete position information.
|
||||
func (s *Scope) Contains(pos token.Pos) bool {
|
||||
return s.pos <= pos && pos < s.end
|
||||
}
|
||||
|
||||
// Innermost returns the innermost (child) scope containing
|
||||
// pos. If pos is not within any scope, the result is nil.
|
||||
// The result is also nil for the Universe scope.
|
||||
// The result is guaranteed to be valid only if the type-checked
|
||||
// AST has complete position information.
|
||||
func (s *Scope) Innermost(pos token.Pos) *Scope {
|
||||
// Package scopes do not have extents since they may be
|
||||
// discontiguous, so iterate over the package's files.
|
||||
if s.parent == Universe {
|
||||
for _, s := range s.children {
|
||||
if inner := s.Innermost(pos); inner != nil {
|
||||
return inner
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if s.Contains(pos) {
|
||||
for _, s := range s.children {
|
||||
if s.Contains(pos) {
|
||||
return s.Innermost(pos)
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteTo writes a string representation of the scope to w,
|
||||
// with the scope elements sorted by name.
|
||||
// The level of indentation is controlled by n >= 0, with
|
||||
// n == 0 for no indentation.
|
||||
// If recurse is set, it also writes nested (children) scopes.
|
||||
func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) {
|
||||
const ind = ". "
|
||||
indn := strings.Repeat(ind, n)
|
||||
|
||||
fmt.Fprintf(w, "%s%s scope %p {", indn, s.comment, s)
|
||||
if len(s.elems) == 0 {
|
||||
fmt.Fprintf(w, "}\n")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Fprintln(w)
|
||||
indn1 := indn + ind
|
||||
for _, name := range s.Names() {
|
||||
fmt.Fprintf(w, "%s%s\n", indn1, s.elems[name])
|
||||
}
|
||||
|
||||
if recurse {
|
||||
for _, s := range s.children {
|
||||
fmt.Fprintln(w)
|
||||
s.WriteTo(w, n+1, recurse)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s}", indn)
|
||||
}
|
||||
|
||||
// String returns a string representation of the scope, for debugging.
|
||||
func (s *Scope) String() string {
|
||||
var buf bytes.Buffer
|
||||
s.WriteTo(&buf, 0, false)
|
||||
return buf.String()
|
||||
}
|
143
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/selection.go
generated
vendored
143
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/selection.go
generated
vendored
@ -1,143 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements Selections.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// SelectionKind describes the kind of a selector expression x.f
|
||||
// (excluding qualified identifiers).
|
||||
type SelectionKind int
|
||||
|
||||
const (
|
||||
FieldVal SelectionKind = iota // x.f is a struct field selector
|
||||
MethodVal // x.f is a method selector
|
||||
MethodExpr // x.f is a method expression
|
||||
)
|
||||
|
||||
// A Selection describes a selector expression x.f.
|
||||
// For the declarations:
|
||||
//
|
||||
// type T struct{ x int; E }
|
||||
// type E struct{}
|
||||
// func (e E) m() {}
|
||||
// var p *T
|
||||
//
|
||||
// the following relations exist:
|
||||
//
|
||||
// Selector Kind Recv Obj Type Index Indirect
|
||||
//
|
||||
// p.x FieldVal T x int {0} true
|
||||
// p.m MethodVal *T m func (e *T) m() {1, 0} true
|
||||
// T.m MethodExpr T m func m(_ T) {1, 0} false
|
||||
//
|
||||
type Selection struct {
|
||||
kind SelectionKind
|
||||
recv Type // type of x
|
||||
obj Object // object denoted by x.f
|
||||
index []int // path from x to x.f
|
||||
indirect bool // set if there was any pointer indirection on the path
|
||||
}
|
||||
|
||||
// Kind returns the selection kind.
|
||||
func (s *Selection) Kind() SelectionKind { return s.kind }
|
||||
|
||||
// Recv returns the type of x in x.f.
|
||||
func (s *Selection) Recv() Type { return s.recv }
|
||||
|
||||
// Obj returns the object denoted by x.f; a *Var for
|
||||
// a field selection, and a *Func in all other cases.
|
||||
func (s *Selection) Obj() Object { return s.obj }
|
||||
|
||||
// Type returns the type of x.f, which may be different from the type of f.
|
||||
// See Selection for more information.
|
||||
func (s *Selection) Type() Type {
|
||||
switch s.kind {
|
||||
case MethodVal:
|
||||
// The type of x.f is a method with its receiver type set
|
||||
// to the type of x.
|
||||
sig := *s.obj.(*Func).typ.(*Signature)
|
||||
recv := *sig.recv
|
||||
recv.typ = s.recv
|
||||
sig.recv = &recv
|
||||
return &sig
|
||||
|
||||
case MethodExpr:
|
||||
// The type of x.f is a function (without receiver)
|
||||
// and an additional first argument with the same type as x.
|
||||
// TODO(gri) Similar code is already in call.go - factor!
|
||||
// TODO(gri) Compute this eagerly to avoid allocations.
|
||||
sig := *s.obj.(*Func).typ.(*Signature)
|
||||
arg0 := *sig.recv
|
||||
sig.recv = nil
|
||||
arg0.typ = s.recv
|
||||
var params []*Var
|
||||
if sig.params != nil {
|
||||
params = sig.params.vars
|
||||
}
|
||||
sig.params = NewTuple(append([]*Var{&arg0}, params...)...)
|
||||
return &sig
|
||||
}
|
||||
|
||||
// In all other cases, the type of x.f is the type of x.
|
||||
return s.obj.Type()
|
||||
}
|
||||
|
||||
// Index describes the path from x to f in x.f.
|
||||
// The last index entry is the field or method index of the type declaring f;
|
||||
// either:
|
||||
//
|
||||
// 1) the list of declared methods of a named type; or
|
||||
// 2) the list of methods of an interface type; or
|
||||
// 3) the list of fields of a struct type.
|
||||
//
|
||||
// The earlier index entries are the indices of the embedded fields implicitly
|
||||
// traversed to get from (the type of) x to f, starting at embedding depth 0.
|
||||
func (s *Selection) Index() []int { return s.index }
|
||||
|
||||
// Indirect reports whether any pointer indirection was required to get from
|
||||
// x to f in x.f.
|
||||
func (s *Selection) Indirect() bool { return s.indirect }
|
||||
|
||||
func (s *Selection) String() string { return SelectionString(s, nil) }
|
||||
|
||||
// SelectionString returns the string form of s.
|
||||
// The Qualifier controls the printing of
|
||||
// package-level objects, and may be nil.
|
||||
//
|
||||
// Examples:
|
||||
// "field (T) f int"
|
||||
// "method (T) f(X) Y"
|
||||
// "method expr (T) f(X) Y"
|
||||
//
|
||||
func SelectionString(s *Selection, qf Qualifier) string {
|
||||
var k string
|
||||
switch s.kind {
|
||||
case FieldVal:
|
||||
k = "field "
|
||||
case MethodVal:
|
||||
k = "method "
|
||||
case MethodExpr:
|
||||
k = "method expr "
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(k)
|
||||
buf.WriteByte('(')
|
||||
WriteType(&buf, s.Recv(), qf)
|
||||
fmt.Fprintf(&buf, ") %s", s.obj.Name())
|
||||
if T := s.Type(); s.kind == FieldVal {
|
||||
buf.WriteByte(' ')
|
||||
WriteType(&buf, T, qf)
|
||||
} else {
|
||||
WriteSignature(&buf, T.(*Signature), qf)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
254
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/sizes.go
generated
vendored
254
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/sizes.go
generated
vendored
@ -1,254 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements Sizes.
|
||||
|
||||
package types
|
||||
|
||||
// Sizes defines the sizing functions for package unsafe.
|
||||
type Sizes interface {
|
||||
// Alignof returns the alignment of a variable of type T.
|
||||
// Alignof must implement the alignment guarantees required by the spec.
|
||||
Alignof(T Type) int64
|
||||
|
||||
// Offsetsof returns the offsets of the given struct fields, in bytes.
|
||||
// Offsetsof must implement the offset guarantees required by the spec.
|
||||
Offsetsof(fields []*Var) []int64
|
||||
|
||||
// Sizeof returns the size of a variable of type T.
|
||||
// Sizeof must implement the size guarantees required by the spec.
|
||||
Sizeof(T Type) int64
|
||||
}
|
||||
|
||||
// StdSizes is a convenience type for creating commonly used Sizes.
|
||||
// It makes the following simplifying assumptions:
|
||||
//
|
||||
// - The size of explicitly sized basic types (int16, etc.) is the
|
||||
// specified size.
|
||||
// - The size of strings and interfaces is 2*WordSize.
|
||||
// - The size of slices is 3*WordSize.
|
||||
// - The size of an array of n elements corresponds to the size of
|
||||
// a struct of n consecutive fields of the array's element type.
|
||||
// - The size of a struct is the offset of the last field plus that
|
||||
// field's size. As with all element types, if the struct is used
|
||||
// in an array its size must first be aligned to a multiple of the
|
||||
// struct's alignment.
|
||||
// - All other types have size WordSize.
|
||||
// - Arrays and structs are aligned per spec definition; all other
|
||||
// types are naturally aligned with a maximum alignment MaxAlign.
|
||||
//
|
||||
// *StdSizes implements Sizes.
|
||||
//
|
||||
type StdSizes struct {
|
||||
WordSize int64 // word size in bytes - must be >= 4 (32bits)
|
||||
MaxAlign int64 // maximum alignment in bytes - must be >= 1
|
||||
}
|
||||
|
||||
func (s *StdSizes) Alignof(T Type) int64 {
|
||||
// For arrays and structs, alignment is defined in terms
|
||||
// of alignment of the elements and fields, respectively.
|
||||
switch t := T.Underlying().(type) {
|
||||
case *Array:
|
||||
// spec: "For a variable x of array type: unsafe.Alignof(x)
|
||||
// is the same as unsafe.Alignof(x[0]), but at least 1."
|
||||
return s.Alignof(t.elem)
|
||||
case *Struct:
|
||||
// spec: "For a variable x of struct type: unsafe.Alignof(x)
|
||||
// is the largest of the values unsafe.Alignof(x.f) for each
|
||||
// field f of x, but at least 1."
|
||||
max := int64(1)
|
||||
for _, f := range t.fields {
|
||||
if a := s.Alignof(f.typ); a > max {
|
||||
max = a
|
||||
}
|
||||
}
|
||||
return max
|
||||
case *Slice, *Interface:
|
||||
// Multiword data structures are effectively structs
|
||||
// in which each element has size WordSize.
|
||||
return s.WordSize
|
||||
case *Basic:
|
||||
// Strings are like slices and interfaces.
|
||||
if t.Info()&IsString != 0 {
|
||||
return s.WordSize
|
||||
}
|
||||
}
|
||||
a := s.Sizeof(T) // may be 0
|
||||
// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
|
||||
if a < 1 {
|
||||
return 1
|
||||
}
|
||||
// complex{64,128} are aligned like [2]float{32,64}.
|
||||
if isComplex(T) {
|
||||
a /= 2
|
||||
}
|
||||
if a > s.MaxAlign {
|
||||
return s.MaxAlign
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func (s *StdSizes) Offsetsof(fields []*Var) []int64 {
|
||||
offsets := make([]int64, len(fields))
|
||||
var o int64
|
||||
for i, f := range fields {
|
||||
a := s.Alignof(f.typ)
|
||||
o = align(o, a)
|
||||
offsets[i] = o
|
||||
o += s.Sizeof(f.typ)
|
||||
}
|
||||
return offsets
|
||||
}
|
||||
|
||||
var basicSizes = [...]byte{
|
||||
Bool: 1,
|
||||
Int8: 1,
|
||||
Int16: 2,
|
||||
Int32: 4,
|
||||
Int64: 8,
|
||||
Uint8: 1,
|
||||
Uint16: 2,
|
||||
Uint32: 4,
|
||||
Uint64: 8,
|
||||
Float32: 4,
|
||||
Float64: 8,
|
||||
Complex64: 8,
|
||||
Complex128: 16,
|
||||
}
|
||||
|
||||
func (s *StdSizes) Sizeof(T Type) int64 {
|
||||
switch t := T.Underlying().(type) {
|
||||
case *Basic:
|
||||
assert(isTyped(T))
|
||||
k := t.kind
|
||||
if int(k) < len(basicSizes) {
|
||||
if s := basicSizes[k]; s > 0 {
|
||||
return int64(s)
|
||||
}
|
||||
}
|
||||
if k == String {
|
||||
return s.WordSize * 2
|
||||
}
|
||||
case *Array:
|
||||
n := t.len
|
||||
if n <= 0 {
|
||||
return 0
|
||||
}
|
||||
// n > 0
|
||||
a := s.Alignof(t.elem)
|
||||
z := s.Sizeof(t.elem)
|
||||
return align(z, a)*(n-1) + z
|
||||
case *Slice:
|
||||
return s.WordSize * 3
|
||||
case *Struct:
|
||||
n := t.NumFields()
|
||||
if n == 0 {
|
||||
return 0
|
||||
}
|
||||
offsets := s.Offsetsof(t.fields)
|
||||
return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
|
||||
case *Interface:
|
||||
return s.WordSize * 2
|
||||
}
|
||||
return s.WordSize // catch-all
|
||||
}
|
||||
|
||||
// common architecture word sizes and alignments
|
||||
var gcArchSizes = map[string]*StdSizes{
|
||||
"386": {4, 4},
|
||||
"arm": {4, 4},
|
||||
"arm64": {8, 8},
|
||||
"amd64": {8, 8},
|
||||
"amd64p32": {4, 8},
|
||||
"mips": {4, 4},
|
||||
"mipsle": {4, 4},
|
||||
"mips64": {8, 8},
|
||||
"mips64le": {8, 8},
|
||||
"ppc64": {8, 8},
|
||||
"ppc64le": {8, 8},
|
||||
"s390x": {8, 8},
|
||||
// When adding more architectures here,
|
||||
// update the doc string of SizesFor below.
|
||||
}
|
||||
|
||||
// SizesFor returns the Sizes used by a compiler for an architecture.
|
||||
// The result is nil if a compiler/architecture pair is not known.
|
||||
//
|
||||
// Supported architectures for compiler "gc":
|
||||
// "386", "arm", "arm64", "amd64", "amd64p32", "mips", "mipsle",
|
||||
// "mips64", "mips64le", "ppc64", "ppc64le", "s390x".
|
||||
func SizesFor(compiler, arch string) Sizes {
|
||||
if compiler != "gc" {
|
||||
return nil
|
||||
}
|
||||
s, ok := gcArchSizes[arch]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// stdSizes is used if Config.Sizes == nil.
|
||||
var stdSizes = SizesFor("gc", "amd64")
|
||||
|
||||
func (conf *Config) alignof(T Type) int64 {
|
||||
if s := conf.Sizes; s != nil {
|
||||
if a := s.Alignof(T); a >= 1 {
|
||||
return a
|
||||
}
|
||||
panic("Config.Sizes.Alignof returned an alignment < 1")
|
||||
}
|
||||
return stdSizes.Alignof(T)
|
||||
}
|
||||
|
||||
func (conf *Config) offsetsof(T *Struct) []int64 {
|
||||
var offsets []int64
|
||||
if T.NumFields() > 0 {
|
||||
// compute offsets on demand
|
||||
if s := conf.Sizes; s != nil {
|
||||
offsets = s.Offsetsof(T.fields)
|
||||
// sanity checks
|
||||
if len(offsets) != T.NumFields() {
|
||||
panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
|
||||
}
|
||||
for _, o := range offsets {
|
||||
if o < 0 {
|
||||
panic("Config.Sizes.Offsetsof returned an offset < 0")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
offsets = stdSizes.Offsetsof(T.fields)
|
||||
}
|
||||
}
|
||||
return offsets
|
||||
}
|
||||
|
||||
// offsetof returns the offset of the field specified via
|
||||
// the index sequence relative to typ. All embedded fields
|
||||
// must be structs (rather than pointer to structs).
|
||||
func (conf *Config) offsetof(typ Type, index []int) int64 {
|
||||
var o int64
|
||||
for _, i := range index {
|
||||
s := typ.Underlying().(*Struct)
|
||||
o += conf.offsetsof(s)[i]
|
||||
typ = s.fields[i].typ
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (conf *Config) sizeof(T Type) int64 {
|
||||
if s := conf.Sizes; s != nil {
|
||||
if z := s.Sizeof(T); z >= 0 {
|
||||
return z
|
||||
}
|
||||
panic("Config.Sizes.Sizeof returned a size < 0")
|
||||
}
|
||||
return stdSizes.Sizeof(T)
|
||||
}
|
||||
|
||||
// align returns the smallest y >= x such that y % a == 0.
|
||||
func align(x, a int64) int64 {
|
||||
y := x + a - 1
|
||||
return y - y%a
|
||||
}
|
870
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/stmt.go
generated
vendored
870
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/stmt.go
generated
vendored
@ -1,870 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements typechecking of statements.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt) {
|
||||
if trace {
|
||||
if name == "" {
|
||||
name = "<function literal>"
|
||||
}
|
||||
fmt.Printf("--- %s: %s {\n", name, sig)
|
||||
defer fmt.Println("--- <end>")
|
||||
}
|
||||
|
||||
// set function scope extent
|
||||
sig.scope.pos = body.Pos()
|
||||
sig.scope.end = body.End()
|
||||
|
||||
// save/restore current context and setup function context
|
||||
// (and use 0 indentation at function start)
|
||||
defer func(ctxt context, indent int) {
|
||||
check.context = ctxt
|
||||
check.indent = indent
|
||||
}(check.context, check.indent)
|
||||
check.context = context{
|
||||
decl: decl,
|
||||
scope: sig.scope,
|
||||
sig: sig,
|
||||
}
|
||||
check.indent = 0
|
||||
|
||||
check.stmtList(0, body.List)
|
||||
|
||||
if check.hasLabel {
|
||||
check.labels(body)
|
||||
}
|
||||
|
||||
if sig.results.Len() > 0 && !check.isTerminating(body, "") {
|
||||
check.error(body.Rbrace, "missing return")
|
||||
}
|
||||
|
||||
// spec: "Implementation restriction: A compiler may make it illegal to
|
||||
// declare a variable inside a function body if the variable is never used."
|
||||
// (One could check each scope after use, but that distributes this check
|
||||
// over several places because CloseScope is not always called explicitly.)
|
||||
check.usage(sig.scope)
|
||||
}
|
||||
|
||||
func (check *Checker) usage(scope *Scope) {
|
||||
var unused []*Var
|
||||
for _, elem := range scope.elems {
|
||||
if v, _ := elem.(*Var); v != nil && !v.used {
|
||||
unused = append(unused, v)
|
||||
}
|
||||
}
|
||||
sort.Slice(unused, func(i, j int) bool {
|
||||
return unused[i].pos < unused[j].pos
|
||||
})
|
||||
for _, v := range unused {
|
||||
check.softErrorf(v.pos, "%s declared but not used", v.name)
|
||||
}
|
||||
|
||||
for _, scope := range scope.children {
|
||||
// Don't go inside closure scopes a second time;
|
||||
// they are handled explicitly by funcBody.
|
||||
if !scope.isFunc {
|
||||
check.usage(scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stmtContext is a bitset describing which
|
||||
// control-flow statements are permissible,
|
||||
// and provides additional context information
|
||||
// for better error messages.
|
||||
type stmtContext uint
|
||||
|
||||
const (
|
||||
// permissible control-flow statements
|
||||
breakOk stmtContext = 1 << iota
|
||||
continueOk
|
||||
fallthroughOk
|
||||
|
||||
// additional context information
|
||||
finalSwitchCase
|
||||
)
|
||||
|
||||
func (check *Checker) simpleStmt(s ast.Stmt) {
|
||||
if s != nil {
|
||||
check.stmt(0, s)
|
||||
}
|
||||
}
|
||||
|
||||
func trimTrailingEmptyStmts(list []ast.Stmt) []ast.Stmt {
|
||||
for i := len(list); i > 0; i-- {
|
||||
if _, ok := list[i-1].(*ast.EmptyStmt); !ok {
|
||||
return list[:i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (check *Checker) stmtList(ctxt stmtContext, list []ast.Stmt) {
|
||||
ok := ctxt&fallthroughOk != 0
|
||||
inner := ctxt &^ fallthroughOk
|
||||
list = trimTrailingEmptyStmts(list) // trailing empty statements are "invisible" to fallthrough analysis
|
||||
for i, s := range list {
|
||||
inner := inner
|
||||
if ok && i+1 == len(list) {
|
||||
inner |= fallthroughOk
|
||||
}
|
||||
check.stmt(inner, s)
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) multipleDefaults(list []ast.Stmt) {
|
||||
var first ast.Stmt
|
||||
for _, s := range list {
|
||||
var d ast.Stmt
|
||||
switch c := s.(type) {
|
||||
case *ast.CaseClause:
|
||||
if len(c.List) == 0 {
|
||||
d = s
|
||||
}
|
||||
case *ast.CommClause:
|
||||
if c.Comm == nil {
|
||||
d = s
|
||||
}
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "case/communication clause expected")
|
||||
}
|
||||
if d != nil {
|
||||
if first != nil {
|
||||
check.errorf(d.Pos(), "multiple defaults (first at %s)", check.fset.Position(first.Pos()))
|
||||
} else {
|
||||
first = d
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) openScope(s ast.Stmt, comment string) {
|
||||
scope := NewScope(check.scope, s.Pos(), s.End(), comment)
|
||||
check.recordScope(s, scope)
|
||||
check.scope = scope
|
||||
}
|
||||
|
||||
func (check *Checker) closeScope() {
|
||||
check.scope = check.scope.Parent()
|
||||
}
|
||||
|
||||
func assignOp(op token.Token) token.Token {
|
||||
// token_test.go verifies the token ordering this function relies on
|
||||
if token.ADD_ASSIGN <= op && op <= token.AND_NOT_ASSIGN {
|
||||
return op + (token.ADD - token.ADD_ASSIGN)
|
||||
}
|
||||
return token.ILLEGAL
|
||||
}
|
||||
|
||||
func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) {
|
||||
var x operand
|
||||
var msg string
|
||||
switch check.rawExpr(&x, call, nil) {
|
||||
case conversion:
|
||||
msg = "requires function call, not conversion"
|
||||
case expression:
|
||||
msg = "discards result of"
|
||||
case statement:
|
||||
return
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
check.errorf(x.pos(), "%s %s %s", keyword, msg, &x)
|
||||
}
|
||||
|
||||
// goVal returns the Go value for val, or nil.
|
||||
func goVal(val constant.Value) interface{} {
|
||||
// val should exist, but be conservative and check
|
||||
if val == nil {
|
||||
return nil
|
||||
}
|
||||
// Match implementation restriction of other compilers.
|
||||
// gc only checks duplicates for integer, floating-point
|
||||
// and string values, so only create Go values for these
|
||||
// types.
|
||||
switch val.Kind() {
|
||||
case constant.Int:
|
||||
if x, ok := constant.Int64Val(val); ok {
|
||||
return x
|
||||
}
|
||||
if x, ok := constant.Uint64Val(val); ok {
|
||||
return x
|
||||
}
|
||||
case constant.Float:
|
||||
if x, ok := constant.Float64Val(val); ok {
|
||||
return x
|
||||
}
|
||||
case constant.String:
|
||||
return constant.StringVal(val)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A valueMap maps a case value (of a basic Go type) to a list of positions
|
||||
// where the same case value appeared, together with the corresponding case
|
||||
// types.
|
||||
// Since two case values may have the same "underlying" value but different
|
||||
// types we need to also check the value's types (e.g., byte(1) vs myByte(1))
|
||||
// when the switch expression is of interface type.
|
||||
type (
|
||||
valueMap map[interface{}][]valueType // underlying Go value -> valueType
|
||||
valueType struct {
|
||||
pos token.Pos
|
||||
typ Type
|
||||
}
|
||||
)
|
||||
|
||||
func (check *Checker) caseValues(x *operand, values []ast.Expr, seen valueMap) {
|
||||
L:
|
||||
for _, e := range values {
|
||||
var v operand
|
||||
check.expr(&v, e)
|
||||
if x.mode == invalid || v.mode == invalid {
|
||||
continue L
|
||||
}
|
||||
check.convertUntyped(&v, x.typ)
|
||||
if v.mode == invalid {
|
||||
continue L
|
||||
}
|
||||
// Order matters: By comparing v against x, error positions are at the case values.
|
||||
res := v // keep original v unchanged
|
||||
check.comparison(&res, x, token.EQL)
|
||||
if res.mode == invalid {
|
||||
continue L
|
||||
}
|
||||
if v.mode != constant_ {
|
||||
continue L // we're done
|
||||
}
|
||||
// look for duplicate values
|
||||
if val := goVal(v.val); val != nil {
|
||||
// look for duplicate types for a given value
|
||||
// (quadratic algorithm, but these lists tend to be very short)
|
||||
for _, vt := range seen[val] {
|
||||
if Identical(v.typ, vt.typ) {
|
||||
check.errorf(v.pos(), "duplicate case %s in expression switch", &v)
|
||||
check.error(vt.pos, "\tprevious case") // secondary error, \t indented
|
||||
continue L
|
||||
}
|
||||
}
|
||||
seen[val] = append(seen[val], valueType{v.pos(), v.typ})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]token.Pos) (T Type) {
|
||||
L:
|
||||
for _, e := range types {
|
||||
T = check.typOrNil(e)
|
||||
if T == Typ[Invalid] {
|
||||
continue L
|
||||
}
|
||||
// look for duplicate types
|
||||
// (quadratic algorithm, but type switches tend to be reasonably small)
|
||||
for t, pos := range seen {
|
||||
if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
|
||||
// talk about "case" rather than "type" because of nil case
|
||||
Ts := "nil"
|
||||
if T != nil {
|
||||
Ts = T.String()
|
||||
}
|
||||
check.errorf(e.Pos(), "duplicate case %s in type switch", Ts)
|
||||
check.error(pos, "\tprevious case") // secondary error, \t indented
|
||||
continue L
|
||||
}
|
||||
}
|
||||
seen[T] = e.Pos()
|
||||
if T != nil {
|
||||
check.typeAssertion(e.Pos(), x, xtyp, T)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// stmt typechecks statement s.
|
||||
func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||
// statements cannot use iota in general
|
||||
// (constant declarations set it explicitly)
|
||||
assert(check.iota == nil)
|
||||
|
||||
// statements must end with the same top scope as they started with
|
||||
if debug {
|
||||
defer func(scope *Scope) {
|
||||
// don't check if code is panicking
|
||||
if p := recover(); p != nil {
|
||||
panic(p)
|
||||
}
|
||||
assert(scope == check.scope)
|
||||
}(check.scope)
|
||||
}
|
||||
|
||||
inner := ctxt &^ (fallthroughOk | finalSwitchCase)
|
||||
switch s := s.(type) {
|
||||
case *ast.BadStmt, *ast.EmptyStmt:
|
||||
// ignore
|
||||
|
||||
case *ast.DeclStmt:
|
||||
check.declStmt(s.Decl)
|
||||
|
||||
case *ast.LabeledStmt:
|
||||
check.hasLabel = true
|
||||
check.stmt(ctxt, s.Stmt)
|
||||
|
||||
case *ast.ExprStmt:
|
||||
// spec: "With the exception of specific built-in functions,
|
||||
// function and method calls and receive operations can appear
|
||||
// in statement context. Such statements may be parenthesized."
|
||||
var x operand
|
||||
kind := check.rawExpr(&x, s.X, nil)
|
||||
var msg string
|
||||
switch x.mode {
|
||||
default:
|
||||
if kind == statement {
|
||||
return
|
||||
}
|
||||
msg = "is not used"
|
||||
case builtin:
|
||||
msg = "must be called"
|
||||
case typexpr:
|
||||
msg = "is not an expression"
|
||||
}
|
||||
check.errorf(x.pos(), "%s %s", &x, msg)
|
||||
|
||||
case *ast.SendStmt:
|
||||
var ch, x operand
|
||||
check.expr(&ch, s.Chan)
|
||||
check.expr(&x, s.Value)
|
||||
if ch.mode == invalid || x.mode == invalid {
|
||||
return
|
||||
}
|
||||
|
||||
tch, ok := ch.typ.Underlying().(*Chan)
|
||||
if !ok {
|
||||
check.invalidOp(s.Arrow, "cannot send to non-chan type %s", ch.typ)
|
||||
return
|
||||
}
|
||||
|
||||
if tch.dir == RecvOnly {
|
||||
check.invalidOp(s.Arrow, "cannot send to receive-only type %s", tch)
|
||||
return
|
||||
}
|
||||
|
||||
check.assignment(&x, tch.elem, "send")
|
||||
|
||||
case *ast.IncDecStmt:
|
||||
var op token.Token
|
||||
switch s.Tok {
|
||||
case token.INC:
|
||||
op = token.ADD
|
||||
case token.DEC:
|
||||
op = token.SUB
|
||||
default:
|
||||
check.invalidAST(s.TokPos, "unknown inc/dec operation %s", s.Tok)
|
||||
return
|
||||
}
|
||||
|
||||
var x operand
|
||||
check.expr(&x, s.X)
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
if !isNumeric(x.typ) {
|
||||
check.invalidOp(s.X.Pos(), "%s%s (non-numeric type %s)", s.X, s.Tok, x.typ)
|
||||
return
|
||||
}
|
||||
|
||||
Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position
|
||||
check.binary(&x, nil, s.X, Y, op)
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
check.assignVar(s.X, &x)
|
||||
|
||||
case *ast.AssignStmt:
|
||||
switch s.Tok {
|
||||
case token.ASSIGN, token.DEFINE:
|
||||
if len(s.Lhs) == 0 {
|
||||
check.invalidAST(s.Pos(), "missing lhs in assignment")
|
||||
return
|
||||
}
|
||||
if s.Tok == token.DEFINE {
|
||||
check.shortVarDecl(s.TokPos, s.Lhs, s.Rhs)
|
||||
} else {
|
||||
// regular assignment
|
||||
check.assignVars(s.Lhs, s.Rhs)
|
||||
}
|
||||
|
||||
default:
|
||||
// assignment operations
|
||||
if len(s.Lhs) != 1 || len(s.Rhs) != 1 {
|
||||
check.errorf(s.TokPos, "assignment operation %s requires single-valued expressions", s.Tok)
|
||||
return
|
||||
}
|
||||
op := assignOp(s.Tok)
|
||||
if op == token.ILLEGAL {
|
||||
check.invalidAST(s.TokPos, "unknown assignment operation %s", s.Tok)
|
||||
return
|
||||
}
|
||||
var x operand
|
||||
check.binary(&x, nil, s.Lhs[0], s.Rhs[0], op)
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
check.assignVar(s.Lhs[0], &x)
|
||||
}
|
||||
|
||||
case *ast.GoStmt:
|
||||
check.suspendedCall("go", s.Call)
|
||||
|
||||
case *ast.DeferStmt:
|
||||
check.suspendedCall("defer", s.Call)
|
||||
|
||||
case *ast.ReturnStmt:
|
||||
res := check.sig.results
|
||||
if res.Len() > 0 {
|
||||
// function returns results
|
||||
// (if one, say the first, result parameter is named, all of them are named)
|
||||
if len(s.Results) == 0 && res.vars[0].name != "" {
|
||||
// spec: "Implementation restriction: A compiler may disallow an empty expression
|
||||
// list in a "return" statement if a different entity (constant, type, or variable)
|
||||
// with the same name as a result parameter is in scope at the place of the return."
|
||||
for _, obj := range res.vars {
|
||||
if _, alt := check.scope.LookupParent(obj.name, check.pos); alt != nil && alt != obj {
|
||||
check.errorf(s.Pos(), "result parameter %s not in scope at return", obj.name)
|
||||
check.errorf(alt.Pos(), "\tinner declaration of %s", obj)
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// return has results or result parameters are unnamed
|
||||
check.initVars(res.vars, s.Results, s.Return)
|
||||
}
|
||||
} else if len(s.Results) > 0 {
|
||||
check.error(s.Results[0].Pos(), "no result values expected")
|
||||
check.use(s.Results...)
|
||||
}
|
||||
|
||||
case *ast.BranchStmt:
|
||||
if s.Label != nil {
|
||||
check.hasLabel = true
|
||||
return // checked in 2nd pass (check.labels)
|
||||
}
|
||||
switch s.Tok {
|
||||
case token.BREAK:
|
||||
if ctxt&breakOk == 0 {
|
||||
check.error(s.Pos(), "break not in for, switch, or select statement")
|
||||
}
|
||||
case token.CONTINUE:
|
||||
if ctxt&continueOk == 0 {
|
||||
check.error(s.Pos(), "continue not in for statement")
|
||||
}
|
||||
case token.FALLTHROUGH:
|
||||
if ctxt&fallthroughOk == 0 {
|
||||
msg := "fallthrough statement out of place"
|
||||
if ctxt&finalSwitchCase != 0 {
|
||||
msg = "cannot fallthrough final case in switch"
|
||||
}
|
||||
check.error(s.Pos(), msg)
|
||||
}
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "branch statement: %s", s.Tok)
|
||||
}
|
||||
|
||||
case *ast.BlockStmt:
|
||||
check.openScope(s, "block")
|
||||
defer check.closeScope()
|
||||
|
||||
check.stmtList(inner, s.List)
|
||||
|
||||
case *ast.IfStmt:
|
||||
check.openScope(s, "if")
|
||||
defer check.closeScope()
|
||||
|
||||
check.simpleStmt(s.Init)
|
||||
var x operand
|
||||
check.expr(&x, s.Cond)
|
||||
if x.mode != invalid && !isBoolean(x.typ) {
|
||||
check.error(s.Cond.Pos(), "non-boolean condition in if statement")
|
||||
}
|
||||
check.stmt(inner, s.Body)
|
||||
// The parser produces a correct AST but if it was modified
|
||||
// elsewhere the else branch may be invalid. Check again.
|
||||
switch s.Else.(type) {
|
||||
case nil, *ast.BadStmt:
|
||||
// valid or error already reported
|
||||
case *ast.IfStmt, *ast.BlockStmt:
|
||||
check.stmt(inner, s.Else)
|
||||
default:
|
||||
check.error(s.Else.Pos(), "invalid else branch in if statement")
|
||||
}
|
||||
|
||||
case *ast.SwitchStmt:
|
||||
inner |= breakOk
|
||||
check.openScope(s, "switch")
|
||||
defer check.closeScope()
|
||||
|
||||
check.simpleStmt(s.Init)
|
||||
var x operand
|
||||
if s.Tag != nil {
|
||||
check.expr(&x, s.Tag)
|
||||
// By checking assignment of x to an invisible temporary
|
||||
// (as a compiler would), we get all the relevant checks.
|
||||
check.assignment(&x, nil, "switch expression")
|
||||
} else {
|
||||
// spec: "A missing switch expression is
|
||||
// equivalent to the boolean value true."
|
||||
x.mode = constant_
|
||||
x.typ = Typ[Bool]
|
||||
x.val = constant.MakeBool(true)
|
||||
x.expr = &ast.Ident{NamePos: s.Body.Lbrace, Name: "true"}
|
||||
}
|
||||
|
||||
check.multipleDefaults(s.Body.List)
|
||||
|
||||
seen := make(valueMap) // map of seen case values to positions and types
|
||||
for i, c := range s.Body.List {
|
||||
clause, _ := c.(*ast.CaseClause)
|
||||
if clause == nil {
|
||||
check.invalidAST(c.Pos(), "incorrect expression switch case")
|
||||
continue
|
||||
}
|
||||
check.caseValues(&x, clause.List, seen)
|
||||
check.openScope(clause, "case")
|
||||
inner := inner
|
||||
if i+1 < len(s.Body.List) {
|
||||
inner |= fallthroughOk
|
||||
} else {
|
||||
inner |= finalSwitchCase
|
||||
}
|
||||
check.stmtList(inner, clause.Body)
|
||||
check.closeScope()
|
||||
}
|
||||
|
||||
case *ast.TypeSwitchStmt:
|
||||
inner |= breakOk
|
||||
check.openScope(s, "type switch")
|
||||
defer check.closeScope()
|
||||
|
||||
check.simpleStmt(s.Init)
|
||||
|
||||
// A type switch guard must be of the form:
|
||||
//
|
||||
// TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" .
|
||||
//
|
||||
// The parser is checking syntactic correctness;
|
||||
// remaining syntactic errors are considered AST errors here.
|
||||
// TODO(gri) better factoring of error handling (invalid ASTs)
|
||||
//
|
||||
var lhs *ast.Ident // lhs identifier or nil
|
||||
var rhs ast.Expr
|
||||
switch guard := s.Assign.(type) {
|
||||
case *ast.ExprStmt:
|
||||
rhs = guard.X
|
||||
case *ast.AssignStmt:
|
||||
if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 {
|
||||
check.invalidAST(s.Pos(), "incorrect form of type switch guard")
|
||||
return
|
||||
}
|
||||
|
||||
lhs, _ = guard.Lhs[0].(*ast.Ident)
|
||||
if lhs == nil {
|
||||
check.invalidAST(s.Pos(), "incorrect form of type switch guard")
|
||||
return
|
||||
}
|
||||
|
||||
if lhs.Name == "_" {
|
||||
// _ := x.(type) is an invalid short variable declaration
|
||||
check.softErrorf(lhs.Pos(), "no new variable on left side of :=")
|
||||
lhs = nil // avoid declared but not used error below
|
||||
} else {
|
||||
check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause
|
||||
}
|
||||
|
||||
rhs = guard.Rhs[0]
|
||||
|
||||
default:
|
||||
check.invalidAST(s.Pos(), "incorrect form of type switch guard")
|
||||
return
|
||||
}
|
||||
|
||||
// rhs must be of the form: expr.(type) and expr must be an interface
|
||||
expr, _ := rhs.(*ast.TypeAssertExpr)
|
||||
if expr == nil || expr.Type != nil {
|
||||
check.invalidAST(s.Pos(), "incorrect form of type switch guard")
|
||||
return
|
||||
}
|
||||
var x operand
|
||||
check.expr(&x, expr.X)
|
||||
if x.mode == invalid {
|
||||
return
|
||||
}
|
||||
xtyp, _ := x.typ.Underlying().(*Interface)
|
||||
if xtyp == nil {
|
||||
check.errorf(x.pos(), "%s is not an interface", &x)
|
||||
return
|
||||
}
|
||||
|
||||
check.multipleDefaults(s.Body.List)
|
||||
|
||||
var lhsVars []*Var // list of implicitly declared lhs variables
|
||||
seen := make(map[Type]token.Pos) // map of seen types to positions
|
||||
for _, s := range s.Body.List {
|
||||
clause, _ := s.(*ast.CaseClause)
|
||||
if clause == nil {
|
||||
check.invalidAST(s.Pos(), "incorrect type switch case")
|
||||
continue
|
||||
}
|
||||
// Check each type in this type switch case.
|
||||
T := check.caseTypes(&x, xtyp, clause.List, seen)
|
||||
check.openScope(clause, "case")
|
||||
// If lhs exists, declare a corresponding variable in the case-local scope.
|
||||
if lhs != nil {
|
||||
// spec: "The TypeSwitchGuard may include a short variable declaration.
|
||||
// When that form is used, the variable is declared at the beginning of
|
||||
// the implicit block in each clause. In clauses with a case listing
|
||||
// exactly one type, the variable has that type; otherwise, the variable
|
||||
// has the type of the expression in the TypeSwitchGuard."
|
||||
if len(clause.List) != 1 || T == nil {
|
||||
T = x.typ
|
||||
}
|
||||
obj := NewVar(lhs.Pos(), check.pkg, lhs.Name, T)
|
||||
scopePos := clause.Pos() + token.Pos(len("default")) // for default clause (len(List) == 0)
|
||||
if n := len(clause.List); n > 0 {
|
||||
scopePos = clause.List[n-1].End()
|
||||
}
|
||||
check.declare(check.scope, nil, obj, scopePos)
|
||||
check.recordImplicit(clause, obj)
|
||||
// For the "declared but not used" error, all lhs variables act as
|
||||
// one; i.e., if any one of them is 'used', all of them are 'used'.
|
||||
// Collect them for later analysis.
|
||||
lhsVars = append(lhsVars, obj)
|
||||
}
|
||||
check.stmtList(inner, clause.Body)
|
||||
check.closeScope()
|
||||
}
|
||||
|
||||
// If lhs exists, we must have at least one lhs variable that was used.
|
||||
if lhs != nil {
|
||||
var used bool
|
||||
for _, v := range lhsVars {
|
||||
if v.used {
|
||||
used = true
|
||||
}
|
||||
v.used = true // avoid usage error when checking entire function
|
||||
}
|
||||
if !used {
|
||||
check.softErrorf(lhs.Pos(), "%s declared but not used", lhs.Name)
|
||||
}
|
||||
}
|
||||
|
||||
case *ast.SelectStmt:
|
||||
inner |= breakOk
|
||||
|
||||
check.multipleDefaults(s.Body.List)
|
||||
|
||||
for _, s := range s.Body.List {
|
||||
clause, _ := s.(*ast.CommClause)
|
||||
if clause == nil {
|
||||
continue // error reported before
|
||||
}
|
||||
|
||||
// clause.Comm must be a SendStmt, RecvStmt, or default case
|
||||
valid := false
|
||||
var rhs ast.Expr // rhs of RecvStmt, or nil
|
||||
switch s := clause.Comm.(type) {
|
||||
case nil, *ast.SendStmt:
|
||||
valid = true
|
||||
case *ast.AssignStmt:
|
||||
if len(s.Rhs) == 1 {
|
||||
rhs = s.Rhs[0]
|
||||
}
|
||||
case *ast.ExprStmt:
|
||||
rhs = s.X
|
||||
}
|
||||
|
||||
// if present, rhs must be a receive operation
|
||||
if rhs != nil {
|
||||
if x, _ := unparen(rhs).(*ast.UnaryExpr); x != nil && x.Op == token.ARROW {
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
check.error(clause.Comm.Pos(), "select case must be send or receive (possibly with assignment)")
|
||||
continue
|
||||
}
|
||||
|
||||
check.openScope(s, "case")
|
||||
if clause.Comm != nil {
|
||||
check.stmt(inner, clause.Comm)
|
||||
}
|
||||
check.stmtList(inner, clause.Body)
|
||||
check.closeScope()
|
||||
}
|
||||
|
||||
case *ast.ForStmt:
|
||||
inner |= breakOk | continueOk
|
||||
check.openScope(s, "for")
|
||||
defer check.closeScope()
|
||||
|
||||
check.simpleStmt(s.Init)
|
||||
if s.Cond != nil {
|
||||
var x operand
|
||||
check.expr(&x, s.Cond)
|
||||
if x.mode != invalid && !isBoolean(x.typ) {
|
||||
check.error(s.Cond.Pos(), "non-boolean condition in for statement")
|
||||
}
|
||||
}
|
||||
check.simpleStmt(s.Post)
|
||||
// spec: "The init statement may be a short variable
|
||||
// declaration, but the post statement must not."
|
||||
if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE {
|
||||
check.softErrorf(s.Pos(), "cannot declare in post statement")
|
||||
// Don't call useLHS here because we want to use the lhs in
|
||||
// this erroneous statement so that we don't get errors about
|
||||
// these lhs variables being declared but not used.
|
||||
check.use(s.Lhs...) // avoid follow-up errors
|
||||
}
|
||||
check.stmt(inner, s.Body)
|
||||
|
||||
case *ast.RangeStmt:
|
||||
inner |= breakOk | continueOk
|
||||
check.openScope(s, "for")
|
||||
defer check.closeScope()
|
||||
|
||||
// check expression to iterate over
|
||||
var x operand
|
||||
check.expr(&x, s.X)
|
||||
|
||||
// determine key/value types
|
||||
var key, val Type
|
||||
if x.mode != invalid {
|
||||
switch typ := x.typ.Underlying().(type) {
|
||||
case *Basic:
|
||||
if isString(typ) {
|
||||
key = Typ[Int]
|
||||
val = universeRune // use 'rune' name
|
||||
}
|
||||
case *Array:
|
||||
key = Typ[Int]
|
||||
val = typ.elem
|
||||
case *Slice:
|
||||
key = Typ[Int]
|
||||
val = typ.elem
|
||||
case *Pointer:
|
||||
if typ, _ := typ.base.Underlying().(*Array); typ != nil {
|
||||
key = Typ[Int]
|
||||
val = typ.elem
|
||||
}
|
||||
case *Map:
|
||||
key = typ.key
|
||||
val = typ.elem
|
||||
case *Chan:
|
||||
key = typ.elem
|
||||
val = Typ[Invalid]
|
||||
if typ.dir == SendOnly {
|
||||
check.errorf(x.pos(), "cannot range over send-only channel %s", &x)
|
||||
// ok to continue
|
||||
}
|
||||
if s.Value != nil {
|
||||
check.errorf(s.Value.Pos(), "iteration over %s permits only one iteration variable", &x)
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if key == nil {
|
||||
check.errorf(x.pos(), "cannot range over %s", &x)
|
||||
// ok to continue
|
||||
}
|
||||
|
||||
// check assignment to/declaration of iteration variables
|
||||
// (irregular assignment, cannot easily map to existing assignment checks)
|
||||
|
||||
// lhs expressions and initialization value (rhs) types
|
||||
lhs := [2]ast.Expr{s.Key, s.Value}
|
||||
rhs := [2]Type{key, val} // key, val may be nil
|
||||
|
||||
if s.Tok == token.DEFINE {
|
||||
// short variable declaration; variable scope starts after the range clause
|
||||
// (the for loop opens a new scope, so variables on the lhs never redeclare
|
||||
// previously declared variables)
|
||||
var vars []*Var
|
||||
for i, lhs := range lhs {
|
||||
if lhs == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// determine lhs variable
|
||||
var obj *Var
|
||||
if ident, _ := lhs.(*ast.Ident); ident != nil {
|
||||
// declare new variable
|
||||
name := ident.Name
|
||||
obj = NewVar(ident.Pos(), check.pkg, name, nil)
|
||||
check.recordDef(ident, obj)
|
||||
// _ variables don't count as new variables
|
||||
if name != "_" {
|
||||
vars = append(vars, obj)
|
||||
}
|
||||
} else {
|
||||
check.errorf(lhs.Pos(), "cannot declare %s", lhs)
|
||||
obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable
|
||||
}
|
||||
|
||||
// initialize lhs variable
|
||||
if typ := rhs[i]; typ != nil {
|
||||
x.mode = value
|
||||
x.expr = lhs // we don't have a better rhs expression to use here
|
||||
x.typ = typ
|
||||
check.initVar(obj, &x, "range clause")
|
||||
} else {
|
||||
obj.typ = Typ[Invalid]
|
||||
obj.used = true // don't complain about unused variable
|
||||
}
|
||||
}
|
||||
|
||||
// declare variables
|
||||
if len(vars) > 0 {
|
||||
scopePos := s.X.End()
|
||||
for _, obj := range vars {
|
||||
// spec: "The scope of a constant or variable identifier declared inside
|
||||
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
|
||||
// for short variable declarations) and ends at the end of the innermost
|
||||
// containing block."
|
||||
check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
|
||||
}
|
||||
} else {
|
||||
check.error(s.TokPos, "no new variables on left side of :=")
|
||||
}
|
||||
} else {
|
||||
// ordinary assignment
|
||||
for i, lhs := range lhs {
|
||||
if lhs == nil {
|
||||
continue
|
||||
}
|
||||
if typ := rhs[i]; typ != nil {
|
||||
x.mode = value
|
||||
x.expr = lhs // we don't have a better rhs expression to use here
|
||||
x.typ = typ
|
||||
check.assignVar(lhs, &x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check.stmt(inner, s.Body)
|
||||
|
||||
default:
|
||||
check.error(s.Pos(), "invalid statement")
|
||||
}
|
||||
}
|
464
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/type.go
generated
vendored
464
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/type.go
generated
vendored
@ -1,464 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package types
|
||||
|
||||
import "sort"
|
||||
|
||||
// A Type represents a type of Go.
|
||||
// All types implement the Type interface.
|
||||
type Type interface {
|
||||
// Underlying returns the underlying type of a type.
|
||||
Underlying() Type
|
||||
|
||||
// String returns a string representation of a type.
|
||||
String() string
|
||||
}
|
||||
|
||||
// BasicKind describes the kind of basic type.
|
||||
type BasicKind int
|
||||
|
||||
const (
|
||||
Invalid BasicKind = iota // type is invalid
|
||||
|
||||
// predeclared types
|
||||
Bool
|
||||
Int
|
||||
Int8
|
||||
Int16
|
||||
Int32
|
||||
Int64
|
||||
Uint
|
||||
Uint8
|
||||
Uint16
|
||||
Uint32
|
||||
Uint64
|
||||
Uintptr
|
||||
Float32
|
||||
Float64
|
||||
Complex64
|
||||
Complex128
|
||||
String
|
||||
UnsafePointer
|
||||
|
||||
// types for untyped values
|
||||
UntypedBool
|
||||
UntypedInt
|
||||
UntypedRune
|
||||
UntypedFloat
|
||||
UntypedComplex
|
||||
UntypedString
|
||||
UntypedNil
|
||||
|
||||
// aliases
|
||||
Byte = Uint8
|
||||
Rune = Int32
|
||||
)
|
||||
|
||||
// BasicInfo is a set of flags describing properties of a basic type.
|
||||
type BasicInfo int
|
||||
|
||||
// Properties of basic types.
|
||||
const (
|
||||
IsBoolean BasicInfo = 1 << iota
|
||||
IsInteger
|
||||
IsUnsigned
|
||||
IsFloat
|
||||
IsComplex
|
||||
IsString
|
||||
IsUntyped
|
||||
|
||||
IsOrdered = IsInteger | IsFloat | IsString
|
||||
IsNumeric = IsInteger | IsFloat | IsComplex
|
||||
IsConstType = IsBoolean | IsNumeric | IsString
|
||||
)
|
||||
|
||||
// A Basic represents a basic type.
|
||||
type Basic struct {
|
||||
kind BasicKind
|
||||
info BasicInfo
|
||||
name string
|
||||
}
|
||||
|
||||
// Kind returns the kind of basic type b.
|
||||
func (b *Basic) Kind() BasicKind { return b.kind }
|
||||
|
||||
// Info returns information about properties of basic type b.
|
||||
func (b *Basic) Info() BasicInfo { return b.info }
|
||||
|
||||
// Name returns the name of basic type b.
|
||||
func (b *Basic) Name() string { return b.name }
|
||||
|
||||
// An Array represents an array type.
|
||||
type Array struct {
|
||||
len int64
|
||||
elem Type
|
||||
}
|
||||
|
||||
// NewArray returns a new array type for the given element type and length.
|
||||
// A negative length indicates an unknown length.
|
||||
func NewArray(elem Type, len int64) *Array { return &Array{len, elem} }
|
||||
|
||||
// Len returns the length of array a.
|
||||
// A negative result indicates an unknown length.
|
||||
func (a *Array) Len() int64 { return a.len }
|
||||
|
||||
// Elem returns element type of array a.
|
||||
func (a *Array) Elem() Type { return a.elem }
|
||||
|
||||
// A Slice represents a slice type.
|
||||
type Slice struct {
|
||||
elem Type
|
||||
}
|
||||
|
||||
// NewSlice returns a new slice type for the given element type.
|
||||
func NewSlice(elem Type) *Slice { return &Slice{elem} }
|
||||
|
||||
// Elem returns the element type of slice s.
|
||||
func (s *Slice) Elem() Type { return s.elem }
|
||||
|
||||
// A Struct represents a struct type.
|
||||
type Struct struct {
|
||||
fields []*Var
|
||||
tags []string // field tags; nil if there are no tags
|
||||
}
|
||||
|
||||
// NewStruct returns a new struct with the given fields and corresponding field tags.
|
||||
// If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be
|
||||
// only as long as required to hold the tag with the largest index i. Consequently,
|
||||
// if no field has a tag, tags may be nil.
|
||||
func NewStruct(fields []*Var, tags []string) *Struct {
|
||||
var fset objset
|
||||
for _, f := range fields {
|
||||
if f.name != "_" && fset.insert(f) != nil {
|
||||
panic("multiple fields with the same name")
|
||||
}
|
||||
}
|
||||
if len(tags) > len(fields) {
|
||||
panic("more tags than fields")
|
||||
}
|
||||
return &Struct{fields: fields, tags: tags}
|
||||
}
|
||||
|
||||
// NumFields returns the number of fields in the struct (including blank and anonymous fields).
|
||||
func (s *Struct) NumFields() int { return len(s.fields) }
|
||||
|
||||
// Field returns the i'th field for 0 <= i < NumFields().
|
||||
func (s *Struct) Field(i int) *Var { return s.fields[i] }
|
||||
|
||||
// Tag returns the i'th field tag for 0 <= i < NumFields().
|
||||
func (s *Struct) Tag(i int) string {
|
||||
if i < len(s.tags) {
|
||||
return s.tags[i]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// A Pointer represents a pointer type.
|
||||
type Pointer struct {
|
||||
base Type // element type
|
||||
}
|
||||
|
||||
// NewPointer returns a new pointer type for the given element (base) type.
|
||||
func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} }
|
||||
|
||||
// Elem returns the element type for the given pointer p.
|
||||
func (p *Pointer) Elem() Type { return p.base }
|
||||
|
||||
// A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple.
|
||||
// Tuples are used as components of signatures and to represent the type of multiple
|
||||
// assignments; they are not first class types of Go.
|
||||
type Tuple struct {
|
||||
vars []*Var
|
||||
}
|
||||
|
||||
// NewTuple returns a new tuple for the given variables.
|
||||
func NewTuple(x ...*Var) *Tuple {
|
||||
if len(x) > 0 {
|
||||
return &Tuple{x}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Len returns the number variables of tuple t.
|
||||
func (t *Tuple) Len() int {
|
||||
if t != nil {
|
||||
return len(t.vars)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// At returns the i'th variable of tuple t.
|
||||
func (t *Tuple) At(i int) *Var { return t.vars[i] }
|
||||
|
||||
// A Signature represents a (non-builtin) function or method type.
|
||||
// The receiver is ignored when comparing signatures for identity.
|
||||
type Signature struct {
|
||||
// We need to keep the scope in Signature (rather than passing it around
|
||||
// and store it in the Func Object) because when type-checking a function
|
||||
// literal we call the general type checker which returns a general Type.
|
||||
// We then unpack the *Signature and use the scope for the literal body.
|
||||
scope *Scope // function scope, present for package-local signatures
|
||||
recv *Var // nil if not a method
|
||||
params *Tuple // (incoming) parameters from left to right; or nil
|
||||
results *Tuple // (outgoing) results from left to right; or nil
|
||||
variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only)
|
||||
}
|
||||
|
||||
// NewSignature returns a new function type for the given receiver, parameters,
|
||||
// and results, either of which may be nil. If variadic is set, the function
|
||||
// is variadic, it must have at least one parameter, and the last parameter
|
||||
// must be of unnamed slice type.
|
||||
func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature {
|
||||
if variadic {
|
||||
n := params.Len()
|
||||
if n == 0 {
|
||||
panic("types.NewSignature: variadic function must have at least one parameter")
|
||||
}
|
||||
if _, ok := params.At(n - 1).typ.(*Slice); !ok {
|
||||
panic("types.NewSignature: variadic parameter must be of unnamed slice type")
|
||||
}
|
||||
}
|
||||
return &Signature{nil, recv, params, results, variadic}
|
||||
}
|
||||
|
||||
// Recv returns the receiver of signature s (if a method), or nil if a
|
||||
// function. It is ignored when comparing signatures for identity.
|
||||
//
|
||||
// For an abstract method, Recv returns the enclosing interface either
|
||||
// as a *Named or an *Interface. Due to embedding, an interface may
|
||||
// contain methods whose receiver type is a different interface.
|
||||
func (s *Signature) Recv() *Var { return s.recv }
|
||||
|
||||
// Params returns the parameters of signature s, or nil.
|
||||
func (s *Signature) Params() *Tuple { return s.params }
|
||||
|
||||
// Results returns the results of signature s, or nil.
|
||||
func (s *Signature) Results() *Tuple { return s.results }
|
||||
|
||||
// Variadic reports whether the signature s is variadic.
|
||||
func (s *Signature) Variadic() bool { return s.variadic }
|
||||
|
||||
// An Interface represents an interface type.
|
||||
type Interface struct {
|
||||
methods []*Func // ordered list of explicitly declared methods
|
||||
embeddeds []*Named // ordered list of explicitly embedded types
|
||||
|
||||
allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset)
|
||||
}
|
||||
|
||||
// emptyInterface represents the empty (completed) interface
|
||||
var emptyInterface = Interface{allMethods: markComplete}
|
||||
|
||||
// markComplete is used to mark an empty interface as completely
|
||||
// set up by setting the allMethods field to a non-nil empty slice.
|
||||
var markComplete = make([]*Func, 0)
|
||||
|
||||
// NewInterface returns a new (incomplete) interface for the given methods and embedded types.
|
||||
// To compute the method set of the interface, Complete must be called.
|
||||
func NewInterface(methods []*Func, embeddeds []*Named) *Interface {
|
||||
typ := new(Interface)
|
||||
|
||||
if len(methods) == 0 && len(embeddeds) == 0 {
|
||||
return typ
|
||||
}
|
||||
|
||||
var mset objset
|
||||
for _, m := range methods {
|
||||
if mset.insert(m) != nil {
|
||||
panic("multiple methods with the same name")
|
||||
}
|
||||
// set receiver
|
||||
// TODO(gri) Ideally, we should use a named type here instead of
|
||||
// typ, for less verbose printing of interface method signatures.
|
||||
m.typ.(*Signature).recv = NewVar(m.pos, m.pkg, "", typ)
|
||||
}
|
||||
sort.Sort(byUniqueMethodName(methods))
|
||||
|
||||
if embeddeds != nil {
|
||||
sort.Sort(byUniqueTypeName(embeddeds))
|
||||
}
|
||||
|
||||
typ.methods = methods
|
||||
typ.embeddeds = embeddeds
|
||||
return typ
|
||||
}
|
||||
|
||||
// NumExplicitMethods returns the number of explicitly declared methods of interface t.
|
||||
func (t *Interface) NumExplicitMethods() int { return len(t.methods) }
|
||||
|
||||
// ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods().
|
||||
// The methods are ordered by their unique Id.
|
||||
func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] }
|
||||
|
||||
// NumEmbeddeds returns the number of embedded types in interface t.
|
||||
func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) }
|
||||
|
||||
// Embedded returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds().
|
||||
// The types are ordered by the corresponding TypeName's unique Id.
|
||||
func (t *Interface) Embedded(i int) *Named { return t.embeddeds[i] }
|
||||
|
||||
// NumMethods returns the total number of methods of interface t.
|
||||
func (t *Interface) NumMethods() int { return len(t.allMethods) }
|
||||
|
||||
// Method returns the i'th method of interface t for 0 <= i < t.NumMethods().
|
||||
// The methods are ordered by their unique Id.
|
||||
func (t *Interface) Method(i int) *Func { return t.allMethods[i] }
|
||||
|
||||
// Empty returns true if t is the empty interface.
|
||||
func (t *Interface) Empty() bool { return len(t.allMethods) == 0 }
|
||||
|
||||
// Complete computes the interface's method set. It must be called by users of
|
||||
// NewInterface after the interface's embedded types are fully defined and
|
||||
// before using the interface type in any way other than to form other types.
|
||||
// Complete returns the receiver.
|
||||
func (t *Interface) Complete() *Interface {
|
||||
if t.allMethods != nil {
|
||||
return t
|
||||
}
|
||||
|
||||
var allMethods []*Func
|
||||
if t.embeddeds == nil {
|
||||
if t.methods == nil {
|
||||
allMethods = make([]*Func, 0, 1)
|
||||
} else {
|
||||
allMethods = t.methods
|
||||
}
|
||||
} else {
|
||||
allMethods = append(allMethods, t.methods...)
|
||||
for _, et := range t.embeddeds {
|
||||
it := et.Underlying().(*Interface)
|
||||
it.Complete()
|
||||
for _, tm := range it.allMethods {
|
||||
// Make a copy of the method and adjust its receiver type.
|
||||
newm := *tm
|
||||
newmtyp := *tm.typ.(*Signature)
|
||||
newm.typ = &newmtyp
|
||||
newmtyp.recv = NewVar(newm.pos, newm.pkg, "", t)
|
||||
allMethods = append(allMethods, &newm)
|
||||
}
|
||||
}
|
||||
sort.Sort(byUniqueMethodName(allMethods))
|
||||
}
|
||||
t.allMethods = allMethods
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// A Map represents a map type.
|
||||
type Map struct {
|
||||
key, elem Type
|
||||
}
|
||||
|
||||
// NewMap returns a new map for the given key and element types.
|
||||
func NewMap(key, elem Type) *Map {
|
||||
return &Map{key, elem}
|
||||
}
|
||||
|
||||
// Key returns the key type of map m.
|
||||
func (m *Map) Key() Type { return m.key }
|
||||
|
||||
// Elem returns the element type of map m.
|
||||
func (m *Map) Elem() Type { return m.elem }
|
||||
|
||||
// A Chan represents a channel type.
|
||||
type Chan struct {
|
||||
dir ChanDir
|
||||
elem Type
|
||||
}
|
||||
|
||||
// A ChanDir value indicates a channel direction.
|
||||
type ChanDir int
|
||||
|
||||
// The direction of a channel is indicated by one of these constants.
|
||||
const (
|
||||
SendRecv ChanDir = iota
|
||||
SendOnly
|
||||
RecvOnly
|
||||
)
|
||||
|
||||
// NewChan returns a new channel type for the given direction and element type.
|
||||
func NewChan(dir ChanDir, elem Type) *Chan {
|
||||
return &Chan{dir, elem}
|
||||
}
|
||||
|
||||
// Dir returns the direction of channel c.
|
||||
func (c *Chan) Dir() ChanDir { return c.dir }
|
||||
|
||||
// Elem returns the element type of channel c.
|
||||
func (c *Chan) Elem() Type { return c.elem }
|
||||
|
||||
// A Named represents a named type.
|
||||
type Named struct {
|
||||
obj *TypeName // corresponding declared object
|
||||
underlying Type // possibly a *Named during setup; never a *Named once set up completely
|
||||
methods []*Func // methods declared for this type (not the method set of this type)
|
||||
}
|
||||
|
||||
// NewNamed returns a new named type for the given type name, underlying type, and associated methods.
|
||||
// If the given type name obj doesn't have a type yet, its type is set to the returned named type.
|
||||
// The underlying type must not be a *Named.
|
||||
func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
|
||||
if _, ok := underlying.(*Named); ok {
|
||||
panic("types.NewNamed: underlying type must not be *Named")
|
||||
}
|
||||
typ := &Named{obj: obj, underlying: underlying, methods: methods}
|
||||
if obj.typ == nil {
|
||||
obj.typ = typ
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
// Obj returns the type name for the named type t.
|
||||
func (t *Named) Obj() *TypeName { return t.obj }
|
||||
|
||||
// NumMethods returns the number of explicit methods whose receiver is named type t.
|
||||
func (t *Named) NumMethods() int { return len(t.methods) }
|
||||
|
||||
// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
|
||||
func (t *Named) Method(i int) *Func { return t.methods[i] }
|
||||
|
||||
// SetUnderlying sets the underlying type and marks t as complete.
|
||||
func (t *Named) SetUnderlying(underlying Type) {
|
||||
if underlying == nil {
|
||||
panic("types.Named.SetUnderlying: underlying type must not be nil")
|
||||
}
|
||||
if _, ok := underlying.(*Named); ok {
|
||||
panic("types.Named.SetUnderlying: underlying type must not be *Named")
|
||||
}
|
||||
t.underlying = underlying
|
||||
}
|
||||
|
||||
// AddMethod adds method m unless it is already in the method list.
|
||||
func (t *Named) AddMethod(m *Func) {
|
||||
if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 {
|
||||
t.methods = append(t.methods, m)
|
||||
}
|
||||
}
|
||||
|
||||
// Implementations for Type methods.
|
||||
|
||||
func (t *Basic) Underlying() Type { return t }
|
||||
func (t *Array) Underlying() Type { return t }
|
||||
func (t *Slice) Underlying() Type { return t }
|
||||
func (t *Struct) Underlying() Type { return t }
|
||||
func (t *Pointer) Underlying() Type { return t }
|
||||
func (t *Tuple) Underlying() Type { return t }
|
||||
func (t *Signature) Underlying() Type { return t }
|
||||
func (t *Interface) Underlying() Type { return t }
|
||||
func (t *Map) Underlying() Type { return t }
|
||||
func (t *Chan) Underlying() Type { return t }
|
||||
func (t *Named) Underlying() Type { return t.underlying }
|
||||
|
||||
func (t *Basic) String() string { return TypeString(t, nil) }
|
||||
func (t *Array) String() string { return TypeString(t, nil) }
|
||||
func (t *Slice) String() string { return TypeString(t, nil) }
|
||||
func (t *Struct) String() string { return TypeString(t, nil) }
|
||||
func (t *Pointer) String() string { return TypeString(t, nil) }
|
||||
func (t *Tuple) String() string { return TypeString(t, nil) }
|
||||
func (t *Signature) String() string { return TypeString(t, nil) }
|
||||
func (t *Interface) String() string { return TypeString(t, nil) }
|
||||
func (t *Map) String() string { return TypeString(t, nil) }
|
||||
func (t *Chan) String() string { return TypeString(t, nil) }
|
||||
func (t *Named) String() string { return TypeString(t, nil) }
|
307
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/typestring.go
generated
vendored
307
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/typestring.go
generated
vendored
@ -1,307 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements printing of types.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// A Qualifier controls how named package-level objects are printed in
|
||||
// calls to TypeString, ObjectString, and SelectionString.
|
||||
//
|
||||
// These three formatting routines call the Qualifier for each
|
||||
// package-level object O, and if the Qualifier returns a non-empty
|
||||
// string p, the object is printed in the form p.O.
|
||||
// If it returns an empty string, only the object name O is printed.
|
||||
//
|
||||
// Using a nil Qualifier is equivalent to using (*Package).Path: the
|
||||
// object is qualified by the import path, e.g., "encoding/json.Marshal".
|
||||
//
|
||||
type Qualifier func(*Package) string
|
||||
|
||||
// RelativeTo(pkg) returns a Qualifier that fully qualifies members of
|
||||
// all packages other than pkg.
|
||||
func RelativeTo(pkg *Package) Qualifier {
|
||||
if pkg == nil {
|
||||
return nil
|
||||
}
|
||||
return func(other *Package) string {
|
||||
if pkg == other {
|
||||
return "" // same package; unqualified
|
||||
}
|
||||
return other.Path()
|
||||
}
|
||||
}
|
||||
|
||||
// If gcCompatibilityMode is set, printing of types is modified
|
||||
// to match the representation of some types in the gc compiler:
|
||||
//
|
||||
// - byte and rune lose their alias name and simply stand for
|
||||
// uint8 and int32 respectively
|
||||
// - embedded interfaces get flattened (the embedding info is lost,
|
||||
// and certain recursive interface types cannot be printed anymore)
|
||||
//
|
||||
// This makes it easier to compare packages computed with the type-
|
||||
// checker vs packages imported from gc export data.
|
||||
//
|
||||
// Caution: This flag affects all uses of WriteType, globally.
|
||||
// It is only provided for testing in conjunction with
|
||||
// gc-generated data.
|
||||
//
|
||||
// This flag is exported in the x/tools/go/types package. We don't
|
||||
// need it at the moment in the std repo and so we don't export it
|
||||
// anymore. We should eventually try to remove it altogether.
|
||||
// TODO(gri) remove this
|
||||
var gcCompatibilityMode bool
|
||||
|
||||
// TypeString returns the string representation of typ.
|
||||
// The Qualifier controls the printing of
|
||||
// package-level objects, and may be nil.
|
||||
func TypeString(typ Type, qf Qualifier) string {
|
||||
var buf bytes.Buffer
|
||||
WriteType(&buf, typ, qf)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// WriteType writes the string representation of typ to buf.
|
||||
// The Qualifier controls the printing of
|
||||
// package-level objects, and may be nil.
|
||||
func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) {
|
||||
writeType(buf, typ, qf, make([]Type, 0, 8))
|
||||
}
|
||||
|
||||
func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
|
||||
// Theoretically, this is a quadratic lookup algorithm, but in
|
||||
// practice deeply nested composite types with unnamed component
|
||||
// types are uncommon. This code is likely more efficient than
|
||||
// using a map.
|
||||
for _, t := range visited {
|
||||
if t == typ {
|
||||
fmt.Fprintf(buf, "○%T", typ) // cycle to typ
|
||||
return
|
||||
}
|
||||
}
|
||||
visited = append(visited, typ)
|
||||
|
||||
switch t := typ.(type) {
|
||||
case nil:
|
||||
buf.WriteString("<nil>")
|
||||
|
||||
case *Basic:
|
||||
if t.kind == UnsafePointer {
|
||||
buf.WriteString("unsafe.")
|
||||
}
|
||||
if gcCompatibilityMode {
|
||||
// forget the alias names
|
||||
switch t.kind {
|
||||
case Byte:
|
||||
t = Typ[Uint8]
|
||||
case Rune:
|
||||
t = Typ[Int32]
|
||||
}
|
||||
}
|
||||
buf.WriteString(t.name)
|
||||
|
||||
case *Array:
|
||||
fmt.Fprintf(buf, "[%d]", t.len)
|
||||
writeType(buf, t.elem, qf, visited)
|
||||
|
||||
case *Slice:
|
||||
buf.WriteString("[]")
|
||||
writeType(buf, t.elem, qf, visited)
|
||||
|
||||
case *Struct:
|
||||
buf.WriteString("struct{")
|
||||
for i, f := range t.fields {
|
||||
if i > 0 {
|
||||
buf.WriteString("; ")
|
||||
}
|
||||
if !f.anonymous {
|
||||
buf.WriteString(f.name)
|
||||
buf.WriteByte(' ')
|
||||
}
|
||||
writeType(buf, f.typ, qf, visited)
|
||||
if tag := t.Tag(i); tag != "" {
|
||||
fmt.Fprintf(buf, " %q", tag)
|
||||
}
|
||||
}
|
||||
buf.WriteByte('}')
|
||||
|
||||
case *Pointer:
|
||||
buf.WriteByte('*')
|
||||
writeType(buf, t.base, qf, visited)
|
||||
|
||||
case *Tuple:
|
||||
writeTuple(buf, t, false, qf, visited)
|
||||
|
||||
case *Signature:
|
||||
buf.WriteString("func")
|
||||
writeSignature(buf, t, qf, visited)
|
||||
|
||||
case *Interface:
|
||||
// We write the source-level methods and embedded types rather
|
||||
// than the actual method set since resolved method signatures
|
||||
// may have non-printable cycles if parameters have anonymous
|
||||
// interface types that (directly or indirectly) embed the
|
||||
// current interface. For instance, consider the result type
|
||||
// of m:
|
||||
//
|
||||
// type T interface{
|
||||
// m() interface{ T }
|
||||
// }
|
||||
//
|
||||
buf.WriteString("interface{")
|
||||
empty := true
|
||||
if gcCompatibilityMode {
|
||||
// print flattened interface
|
||||
// (useful to compare against gc-generated interfaces)
|
||||
for i, m := range t.allMethods {
|
||||
if i > 0 {
|
||||
buf.WriteString("; ")
|
||||
}
|
||||
buf.WriteString(m.name)
|
||||
writeSignature(buf, m.typ.(*Signature), qf, visited)
|
||||
empty = false
|
||||
}
|
||||
} else {
|
||||
// print explicit interface methods and embedded types
|
||||
for i, m := range t.methods {
|
||||
if i > 0 {
|
||||
buf.WriteString("; ")
|
||||
}
|
||||
buf.WriteString(m.name)
|
||||
writeSignature(buf, m.typ.(*Signature), qf, visited)
|
||||
empty = false
|
||||
}
|
||||
for i, typ := range t.embeddeds {
|
||||
if i > 0 || len(t.methods) > 0 {
|
||||
buf.WriteString("; ")
|
||||
}
|
||||
writeType(buf, typ, qf, visited)
|
||||
empty = false
|
||||
}
|
||||
}
|
||||
if t.allMethods == nil || len(t.methods) > len(t.allMethods) {
|
||||
if !empty {
|
||||
buf.WriteByte(' ')
|
||||
}
|
||||
buf.WriteString("/* incomplete */")
|
||||
}
|
||||
buf.WriteByte('}')
|
||||
|
||||
case *Map:
|
||||
buf.WriteString("map[")
|
||||
writeType(buf, t.key, qf, visited)
|
||||
buf.WriteByte(']')
|
||||
writeType(buf, t.elem, qf, visited)
|
||||
|
||||
case *Chan:
|
||||
var s string
|
||||
var parens bool
|
||||
switch t.dir {
|
||||
case SendRecv:
|
||||
s = "chan "
|
||||
// chan (<-chan T) requires parentheses
|
||||
if c, _ := t.elem.(*Chan); c != nil && c.dir == RecvOnly {
|
||||
parens = true
|
||||
}
|
||||
case SendOnly:
|
||||
s = "chan<- "
|
||||
case RecvOnly:
|
||||
s = "<-chan "
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
buf.WriteString(s)
|
||||
if parens {
|
||||
buf.WriteByte('(')
|
||||
}
|
||||
writeType(buf, t.elem, qf, visited)
|
||||
if parens {
|
||||
buf.WriteByte(')')
|
||||
}
|
||||
|
||||
case *Named:
|
||||
s := "<Named w/o object>"
|
||||
if obj := t.obj; obj != nil {
|
||||
if obj.pkg != nil {
|
||||
writePackage(buf, obj.pkg, qf)
|
||||
}
|
||||
// TODO(gri): function-local named types should be displayed
|
||||
// differently from named types at package level to avoid
|
||||
// ambiguity.
|
||||
s = obj.name
|
||||
}
|
||||
buf.WriteString(s)
|
||||
|
||||
default:
|
||||
// For externally defined implementations of Type.
|
||||
buf.WriteString(t.String())
|
||||
}
|
||||
}
|
||||
|
||||
func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visited []Type) {
|
||||
buf.WriteByte('(')
|
||||
if tup != nil {
|
||||
for i, v := range tup.vars {
|
||||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
if v.name != "" {
|
||||
buf.WriteString(v.name)
|
||||
buf.WriteByte(' ')
|
||||
}
|
||||
typ := v.typ
|
||||
if variadic && i == len(tup.vars)-1 {
|
||||
if s, ok := typ.(*Slice); ok {
|
||||
buf.WriteString("...")
|
||||
typ = s.elem
|
||||
} else {
|
||||
// special case:
|
||||
// append(s, "foo"...) leads to signature func([]byte, string...)
|
||||
if t, ok := typ.Underlying().(*Basic); !ok || t.kind != String {
|
||||
panic("internal error: string type expected")
|
||||
}
|
||||
writeType(buf, typ, qf, visited)
|
||||
buf.WriteString("...")
|
||||
continue
|
||||
}
|
||||
}
|
||||
writeType(buf, typ, qf, visited)
|
||||
}
|
||||
}
|
||||
buf.WriteByte(')')
|
||||
}
|
||||
|
||||
// WriteSignature writes the representation of the signature sig to buf,
|
||||
// without a leading "func" keyword.
|
||||
// The Qualifier controls the printing of
|
||||
// package-level objects, and may be nil.
|
||||
func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
|
||||
writeSignature(buf, sig, qf, make([]Type, 0, 8))
|
||||
}
|
||||
|
||||
func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) {
|
||||
writeTuple(buf, sig.params, sig.variadic, qf, visited)
|
||||
|
||||
n := sig.results.Len()
|
||||
if n == 0 {
|
||||
// no result
|
||||
return
|
||||
}
|
||||
|
||||
buf.WriteByte(' ')
|
||||
if n == 1 && sig.results.vars[0].name == "" {
|
||||
// single unnamed result
|
||||
writeType(buf, sig.results.vars[0].typ, qf, visited)
|
||||
return
|
||||
}
|
||||
|
||||
// multiple or named result(s)
|
||||
writeTuple(buf, sig.results, false, qf, visited)
|
||||
}
|
722
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/typexpr.go
generated
vendored
722
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/typexpr.go
generated
vendored
@ -1,722 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements type-checking of identifiers and type expressions.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ident type-checks identifier e and initializes x with the value or type of e.
|
||||
// If an error occurred, x.mode is set to invalid.
|
||||
// For the meaning of def and path, see check.typ, below.
|
||||
//
|
||||
func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeName) {
|
||||
x.mode = invalid
|
||||
x.expr = e
|
||||
|
||||
scope, obj := check.scope.LookupParent(e.Name, check.pos)
|
||||
if obj == nil {
|
||||
if e.Name == "_" {
|
||||
check.errorf(e.Pos(), "cannot use _ as value or type")
|
||||
} else {
|
||||
check.errorf(e.Pos(), "undeclared name: %s", e.Name)
|
||||
}
|
||||
return
|
||||
}
|
||||
check.recordUse(e, obj)
|
||||
|
||||
check.objDecl(obj, def, path)
|
||||
typ := obj.Type()
|
||||
assert(typ != nil)
|
||||
|
||||
// The object may be dot-imported: If so, remove its package from
|
||||
// the map of unused dot imports for the respective file scope.
|
||||
// (This code is only needed for dot-imports. Without them,
|
||||
// we only have to mark variables, see *Var case below).
|
||||
if pkg := obj.Pkg(); pkg != check.pkg && pkg != nil {
|
||||
delete(check.unusedDotImports[scope], pkg)
|
||||
}
|
||||
|
||||
switch obj := obj.(type) {
|
||||
case *PkgName:
|
||||
check.errorf(e.Pos(), "use of package %s not in selector", obj.name)
|
||||
return
|
||||
|
||||
case *Const:
|
||||
check.addDeclDep(obj)
|
||||
if typ == Typ[Invalid] {
|
||||
return
|
||||
}
|
||||
if obj == universeIota {
|
||||
if check.iota == nil {
|
||||
check.errorf(e.Pos(), "cannot use iota outside constant declaration")
|
||||
return
|
||||
}
|
||||
x.val = check.iota
|
||||
} else {
|
||||
x.val = obj.val
|
||||
}
|
||||
assert(x.val != nil)
|
||||
x.mode = constant_
|
||||
|
||||
case *TypeName:
|
||||
x.mode = typexpr
|
||||
// check for cycle
|
||||
// (it's ok to iterate forward because each named type appears at most once in path)
|
||||
for i, prev := range path {
|
||||
if prev == obj {
|
||||
check.errorf(obj.pos, "illegal cycle in declaration of %s", obj.name)
|
||||
// print cycle
|
||||
for _, obj := range path[i:] {
|
||||
check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
|
||||
}
|
||||
check.errorf(obj.Pos(), "\t%s", obj.Name())
|
||||
// maintain x.mode == typexpr despite error
|
||||
typ = Typ[Invalid]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
case *Var:
|
||||
// It's ok to mark non-local variables, but ignore variables
|
||||
// from other packages to avoid potential race conditions with
|
||||
// dot-imported variables.
|
||||
if obj.pkg == check.pkg {
|
||||
obj.used = true
|
||||
}
|
||||
check.addDeclDep(obj)
|
||||
if typ == Typ[Invalid] {
|
||||
return
|
||||
}
|
||||
x.mode = variable
|
||||
|
||||
case *Func:
|
||||
check.addDeclDep(obj)
|
||||
x.mode = value
|
||||
|
||||
case *Builtin:
|
||||
x.id = obj.id
|
||||
x.mode = builtin
|
||||
|
||||
case *Nil:
|
||||
x.mode = value
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
|
||||
x.typ = typ
|
||||
}
|
||||
|
||||
// typExpr type-checks the type expression e and returns its type, or Typ[Invalid].
|
||||
// If def != nil, e is the type specification for the named type def, declared
|
||||
// in a type declaration, and def.underlying will be set to the type of e before
|
||||
// any components of e are type-checked. Path contains the path of named types
|
||||
// referring to this type.
|
||||
//
|
||||
func (check *Checker) typExpr(e ast.Expr, def *Named, path []*TypeName) (T Type) {
|
||||
if trace {
|
||||
check.trace(e.Pos(), "%s", e)
|
||||
check.indent++
|
||||
defer func() {
|
||||
check.indent--
|
||||
check.trace(e.Pos(), "=> %s", T)
|
||||
}()
|
||||
}
|
||||
|
||||
T = check.typExprInternal(e, def, path)
|
||||
assert(isTyped(T))
|
||||
check.recordTypeAndValue(e, typexpr, T, nil)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (check *Checker) typ(e ast.Expr) Type {
|
||||
return check.typExpr(e, nil, nil)
|
||||
}
|
||||
|
||||
// funcType type-checks a function or method type.
|
||||
func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) {
|
||||
scope := NewScope(check.scope, token.NoPos, token.NoPos, "function")
|
||||
scope.isFunc = true
|
||||
check.recordScope(ftyp, scope)
|
||||
|
||||
recvList, _ := check.collectParams(scope, recvPar, false)
|
||||
params, variadic := check.collectParams(scope, ftyp.Params, true)
|
||||
results, _ := check.collectParams(scope, ftyp.Results, false)
|
||||
|
||||
if recvPar != nil {
|
||||
// recv parameter list present (may be empty)
|
||||
// spec: "The receiver is specified via an extra parameter section preceding the
|
||||
// method name. That parameter section must declare a single parameter, the receiver."
|
||||
var recv *Var
|
||||
switch len(recvList) {
|
||||
case 0:
|
||||
check.error(recvPar.Pos(), "method is missing receiver")
|
||||
recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below
|
||||
default:
|
||||
// more than one receiver
|
||||
check.error(recvList[len(recvList)-1].Pos(), "method must have exactly one receiver")
|
||||
fallthrough // continue with first receiver
|
||||
case 1:
|
||||
recv = recvList[0]
|
||||
}
|
||||
// spec: "The receiver type must be of the form T or *T where T is a type name."
|
||||
// (ignore invalid types - error was reported before)
|
||||
if t, _ := deref(recv.typ); t != Typ[Invalid] {
|
||||
var err string
|
||||
if T, _ := t.(*Named); T != nil {
|
||||
// spec: "The type denoted by T is called the receiver base type; it must not
|
||||
// be a pointer or interface type and it must be declared in the same package
|
||||
// as the method."
|
||||
if T.obj.pkg != check.pkg {
|
||||
err = "type not defined in this package"
|
||||
} else {
|
||||
// TODO(gri) This is not correct if the underlying type is unknown yet.
|
||||
switch u := T.underlying.(type) {
|
||||
case *Basic:
|
||||
// unsafe.Pointer is treated like a regular pointer
|
||||
if u.kind == UnsafePointer {
|
||||
err = "unsafe.Pointer"
|
||||
}
|
||||
case *Pointer, *Interface:
|
||||
err = "pointer or interface type"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = "basic or unnamed type"
|
||||
}
|
||||
if err != "" {
|
||||
check.errorf(recv.pos, "invalid receiver %s (%s)", recv.typ, err)
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
sig.recv = recv
|
||||
}
|
||||
|
||||
sig.scope = scope
|
||||
sig.params = NewTuple(params...)
|
||||
sig.results = NewTuple(results...)
|
||||
sig.variadic = variadic
|
||||
}
|
||||
|
||||
// typExprInternal drives type checking of types.
|
||||
// Must only be called by typExpr.
|
||||
//
|
||||
func (check *Checker) typExprInternal(e ast.Expr, def *Named, path []*TypeName) Type {
|
||||
switch e := e.(type) {
|
||||
case *ast.BadExpr:
|
||||
// ignore - error reported before
|
||||
|
||||
case *ast.Ident:
|
||||
var x operand
|
||||
check.ident(&x, e, def, path)
|
||||
|
||||
switch x.mode {
|
||||
case typexpr:
|
||||
typ := x.typ
|
||||
def.setUnderlying(typ)
|
||||
return typ
|
||||
case invalid:
|
||||
// ignore - error reported before
|
||||
case novalue:
|
||||
check.errorf(x.pos(), "%s used as type", &x)
|
||||
default:
|
||||
check.errorf(x.pos(), "%s is not a type", &x)
|
||||
}
|
||||
|
||||
case *ast.SelectorExpr:
|
||||
var x operand
|
||||
check.selector(&x, e)
|
||||
|
||||
switch x.mode {
|
||||
case typexpr:
|
||||
typ := x.typ
|
||||
def.setUnderlying(typ)
|
||||
return typ
|
||||
case invalid:
|
||||
// ignore - error reported before
|
||||
case novalue:
|
||||
check.errorf(x.pos(), "%s used as type", &x)
|
||||
default:
|
||||
check.errorf(x.pos(), "%s is not a type", &x)
|
||||
}
|
||||
|
||||
case *ast.ParenExpr:
|
||||
return check.typExpr(e.X, def, path)
|
||||
|
||||
case *ast.ArrayType:
|
||||
if e.Len != nil {
|
||||
typ := new(Array)
|
||||
def.setUnderlying(typ)
|
||||
typ.len = check.arrayLength(e.Len)
|
||||
typ.elem = check.typExpr(e.Elt, nil, path)
|
||||
return typ
|
||||
|
||||
} else {
|
||||
typ := new(Slice)
|
||||
def.setUnderlying(typ)
|
||||
typ.elem = check.typ(e.Elt)
|
||||
return typ
|
||||
}
|
||||
|
||||
case *ast.StructType:
|
||||
typ := new(Struct)
|
||||
def.setUnderlying(typ)
|
||||
check.structType(typ, e, path)
|
||||
return typ
|
||||
|
||||
case *ast.StarExpr:
|
||||
typ := new(Pointer)
|
||||
def.setUnderlying(typ)
|
||||
typ.base = check.typ(e.X)
|
||||
return typ
|
||||
|
||||
case *ast.FuncType:
|
||||
typ := new(Signature)
|
||||
def.setUnderlying(typ)
|
||||
check.funcType(typ, nil, e)
|
||||
return typ
|
||||
|
||||
case *ast.InterfaceType:
|
||||
typ := new(Interface)
|
||||
def.setUnderlying(typ)
|
||||
check.interfaceType(typ, e, def, path)
|
||||
return typ
|
||||
|
||||
case *ast.MapType:
|
||||
typ := new(Map)
|
||||
def.setUnderlying(typ)
|
||||
|
||||
typ.key = check.typ(e.Key)
|
||||
typ.elem = check.typ(e.Value)
|
||||
|
||||
// spec: "The comparison operators == and != must be fully defined
|
||||
// for operands of the key type; thus the key type must not be a
|
||||
// function, map, or slice."
|
||||
//
|
||||
// Delay this check because it requires fully setup types;
|
||||
// it is safe to continue in any case (was issue 6667).
|
||||
check.delay(func() {
|
||||
if !Comparable(typ.key) {
|
||||
check.errorf(e.Key.Pos(), "invalid map key type %s", typ.key)
|
||||
}
|
||||
})
|
||||
|
||||
return typ
|
||||
|
||||
case *ast.ChanType:
|
||||
typ := new(Chan)
|
||||
def.setUnderlying(typ)
|
||||
|
||||
dir := SendRecv
|
||||
switch e.Dir {
|
||||
case ast.SEND | ast.RECV:
|
||||
// nothing to do
|
||||
case ast.SEND:
|
||||
dir = SendOnly
|
||||
case ast.RECV:
|
||||
dir = RecvOnly
|
||||
default:
|
||||
check.invalidAST(e.Pos(), "unknown channel direction %d", e.Dir)
|
||||
// ok to continue
|
||||
}
|
||||
|
||||
typ.dir = dir
|
||||
typ.elem = check.typ(e.Value)
|
||||
return typ
|
||||
|
||||
default:
|
||||
check.errorf(e.Pos(), "%s is not a type", e)
|
||||
}
|
||||
|
||||
typ := Typ[Invalid]
|
||||
def.setUnderlying(typ)
|
||||
return typ
|
||||
}
|
||||
|
||||
// typeOrNil type-checks the type expression (or nil value) e
|
||||
// and returns the typ of e, or nil.
|
||||
// If e is neither a type nor nil, typOrNil returns Typ[Invalid].
|
||||
//
|
||||
func (check *Checker) typOrNil(e ast.Expr) Type {
|
||||
var x operand
|
||||
check.rawExpr(&x, e, nil)
|
||||
switch x.mode {
|
||||
case invalid:
|
||||
// ignore - error reported before
|
||||
case novalue:
|
||||
check.errorf(x.pos(), "%s used as type", &x)
|
||||
case typexpr:
|
||||
return x.typ
|
||||
case value:
|
||||
if x.isNil() {
|
||||
return nil
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
check.errorf(x.pos(), "%s is not a type", &x)
|
||||
}
|
||||
return Typ[Invalid]
|
||||
}
|
||||
|
||||
// arrayLength type-checks the array length expression e
|
||||
// and returns the constant length >= 0, or a value < 0
|
||||
// to indicate an error (and thus an unknown length).
|
||||
func (check *Checker) arrayLength(e ast.Expr) int64 {
|
||||
var x operand
|
||||
check.expr(&x, e)
|
||||
if x.mode != constant_ {
|
||||
if x.mode != invalid {
|
||||
check.errorf(x.pos(), "array length %s must be constant", &x)
|
||||
}
|
||||
return -1
|
||||
}
|
||||
if isUntyped(x.typ) || isInteger(x.typ) {
|
||||
if val := constant.ToInt(x.val); val.Kind() == constant.Int {
|
||||
if representableConst(val, check.conf, Typ[Int], nil) {
|
||||
if n, ok := constant.Int64Val(val); ok && n >= 0 {
|
||||
return n
|
||||
}
|
||||
check.errorf(x.pos(), "invalid array length %s", &x)
|
||||
return -1
|
||||
}
|
||||
}
|
||||
}
|
||||
check.errorf(x.pos(), "array length %s must be integer", &x)
|
||||
return -1
|
||||
}
|
||||
|
||||
func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) {
|
||||
if list == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var named, anonymous bool
|
||||
for i, field := range list.List {
|
||||
ftype := field.Type
|
||||
if t, _ := ftype.(*ast.Ellipsis); t != nil {
|
||||
ftype = t.Elt
|
||||
if variadicOk && i == len(list.List)-1 {
|
||||
variadic = true
|
||||
} else {
|
||||
check.invalidAST(field.Pos(), "... not permitted")
|
||||
// ignore ... and continue
|
||||
}
|
||||
}
|
||||
typ := check.typ(ftype)
|
||||
// The parser ensures that f.Tag is nil and we don't
|
||||
// care if a constructed AST contains a non-nil tag.
|
||||
if len(field.Names) > 0 {
|
||||
// named parameter
|
||||
for _, name := range field.Names {
|
||||
if name.Name == "" {
|
||||
check.invalidAST(name.Pos(), "anonymous parameter")
|
||||
// ok to continue
|
||||
}
|
||||
par := NewParam(name.Pos(), check.pkg, name.Name, typ)
|
||||
check.declare(scope, name, par, scope.pos)
|
||||
params = append(params, par)
|
||||
}
|
||||
named = true
|
||||
} else {
|
||||
// anonymous parameter
|
||||
par := NewParam(ftype.Pos(), check.pkg, "", typ)
|
||||
check.recordImplicit(field, par)
|
||||
params = append(params, par)
|
||||
anonymous = true
|
||||
}
|
||||
}
|
||||
|
||||
if named && anonymous {
|
||||
check.invalidAST(list.Pos(), "list contains both named and anonymous parameters")
|
||||
// ok to continue
|
||||
}
|
||||
|
||||
// For a variadic function, change the last parameter's type from T to []T.
|
||||
if variadic && len(params) > 0 {
|
||||
last := params[len(params)-1]
|
||||
last.typ = &Slice{elem: last.typ}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool {
|
||||
if alt := oset.insert(obj); alt != nil {
|
||||
check.errorf(pos, "%s redeclared", obj.Name())
|
||||
check.reportAltDecl(alt)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (check *Checker) interfaceType(iface *Interface, ityp *ast.InterfaceType, def *Named, path []*TypeName) {
|
||||
// empty interface: common case
|
||||
if ityp.Methods == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// The parser ensures that field tags are nil and we don't
|
||||
// care if a constructed AST contains non-nil tags.
|
||||
|
||||
// use named receiver type if available (for better error messages)
|
||||
var recvTyp Type = iface
|
||||
if def != nil {
|
||||
recvTyp = def
|
||||
}
|
||||
|
||||
// Phase 1: Collect explicitly declared methods, the corresponding
|
||||
// signature (AST) expressions, and the list of embedded
|
||||
// type (AST) expressions. Do not resolve signatures or
|
||||
// embedded types yet to avoid cycles referring to this
|
||||
// interface.
|
||||
|
||||
var (
|
||||
mset objset
|
||||
signatures []ast.Expr // list of corresponding method signatures
|
||||
embedded []ast.Expr // list of embedded types
|
||||
)
|
||||
for _, f := range ityp.Methods.List {
|
||||
if len(f.Names) > 0 {
|
||||
// The parser ensures that there's only one method
|
||||
// and we don't care if a constructed AST has more.
|
||||
name := f.Names[0]
|
||||
pos := name.Pos()
|
||||
// spec: "As with all method sets, in an interface type,
|
||||
// each method must have a unique non-blank name."
|
||||
if name.Name == "_" {
|
||||
check.errorf(pos, "invalid method name _")
|
||||
continue
|
||||
}
|
||||
// Don't type-check signature yet - use an
|
||||
// empty signature now and update it later.
|
||||
// Since we know the receiver, set it up now
|
||||
// (required to avoid crash in ptrRecv; see
|
||||
// e.g. test case for issue 6638).
|
||||
// TODO(gri) Consider marking methods signatures
|
||||
// as incomplete, for better error messages. See
|
||||
// also the T4 and T5 tests in testdata/cycles2.src.
|
||||
sig := new(Signature)
|
||||
sig.recv = NewVar(pos, check.pkg, "", recvTyp)
|
||||
m := NewFunc(pos, check.pkg, name.Name, sig)
|
||||
if check.declareInSet(&mset, pos, m) {
|
||||
iface.methods = append(iface.methods, m)
|
||||
iface.allMethods = append(iface.allMethods, m)
|
||||
signatures = append(signatures, f.Type)
|
||||
check.recordDef(name, m)
|
||||
}
|
||||
} else {
|
||||
// embedded type
|
||||
embedded = append(embedded, f.Type)
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 2: Resolve embedded interfaces. Because an interface must not
|
||||
// embed itself (directly or indirectly), each embedded interface
|
||||
// can be fully resolved without depending on any method of this
|
||||
// interface (if there is a cycle or another error, the embedded
|
||||
// type resolves to an invalid type and is ignored).
|
||||
// In particular, the list of methods for each embedded interface
|
||||
// must be complete (it cannot depend on this interface), and so
|
||||
// those methods can be added to the list of all methods of this
|
||||
// interface.
|
||||
|
||||
for _, e := range embedded {
|
||||
pos := e.Pos()
|
||||
typ := check.typExpr(e, nil, path)
|
||||
// Determine underlying embedded (possibly incomplete) type
|
||||
// by following its forward chain.
|
||||
named, _ := typ.(*Named)
|
||||
under := underlying(named)
|
||||
embed, _ := under.(*Interface)
|
||||
if embed == nil {
|
||||
if typ != Typ[Invalid] {
|
||||
check.errorf(pos, "%s is not an interface", typ)
|
||||
}
|
||||
continue
|
||||
}
|
||||
iface.embeddeds = append(iface.embeddeds, named)
|
||||
// collect embedded methods
|
||||
if embed.allMethods == nil {
|
||||
check.errorf(pos, "internal error: incomplete embedded interface %s (issue #18395)", named)
|
||||
}
|
||||
for _, m := range embed.allMethods {
|
||||
if check.declareInSet(&mset, pos, m) {
|
||||
iface.allMethods = append(iface.allMethods, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 3: At this point all methods have been collected for this interface.
|
||||
// It is now safe to type-check the signatures of all explicitly
|
||||
// declared methods, even if they refer to this interface via a cycle
|
||||
// and embed the methods of this interface in a parameter of interface
|
||||
// type.
|
||||
|
||||
for i, m := range iface.methods {
|
||||
expr := signatures[i]
|
||||
typ := check.typ(expr)
|
||||
sig, _ := typ.(*Signature)
|
||||
if sig == nil {
|
||||
if typ != Typ[Invalid] {
|
||||
check.invalidAST(expr.Pos(), "%s is not a method signature", typ)
|
||||
}
|
||||
continue // keep method with empty method signature
|
||||
}
|
||||
// update signature, but keep recv that was set up before
|
||||
old := m.typ.(*Signature)
|
||||
sig.recv = old.recv
|
||||
*old = *sig // update signature (don't replace it!)
|
||||
}
|
||||
|
||||
// TODO(gri) The list of explicit methods is only sorted for now to
|
||||
// produce the same Interface as NewInterface. We may be able to
|
||||
// claim source order in the future. Revisit.
|
||||
sort.Sort(byUniqueMethodName(iface.methods))
|
||||
|
||||
// TODO(gri) The list of embedded types is only sorted for now to
|
||||
// produce the same Interface as NewInterface. We may be able to
|
||||
// claim source order in the future. Revisit.
|
||||
sort.Sort(byUniqueTypeName(iface.embeddeds))
|
||||
|
||||
if iface.allMethods == nil {
|
||||
iface.allMethods = make([]*Func, 0) // mark interface as complete
|
||||
} else {
|
||||
sort.Sort(byUniqueMethodName(iface.allMethods))
|
||||
}
|
||||
}
|
||||
|
||||
// byUniqueTypeName named type lists can be sorted by their unique type names.
|
||||
type byUniqueTypeName []*Named
|
||||
|
||||
func (a byUniqueTypeName) Len() int { return len(a) }
|
||||
func (a byUniqueTypeName) Less(i, j int) bool { return a[i].obj.Id() < a[j].obj.Id() }
|
||||
func (a byUniqueTypeName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
// byUniqueMethodName method lists can be sorted by their unique method names.
|
||||
type byUniqueMethodName []*Func
|
||||
|
||||
func (a byUniqueMethodName) Len() int { return len(a) }
|
||||
func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() }
|
||||
func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
func (check *Checker) tag(t *ast.BasicLit) string {
|
||||
if t != nil {
|
||||
if t.Kind == token.STRING {
|
||||
if val, err := strconv.Unquote(t.Value); err == nil {
|
||||
return val
|
||||
}
|
||||
}
|
||||
check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeName) {
|
||||
list := e.Fields
|
||||
if list == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// struct fields and tags
|
||||
var fields []*Var
|
||||
var tags []string
|
||||
|
||||
// for double-declaration checks
|
||||
var fset objset
|
||||
|
||||
// current field typ and tag
|
||||
var typ Type
|
||||
var tag string
|
||||
add := func(ident *ast.Ident, anonymous bool, pos token.Pos) {
|
||||
if tag != "" && tags == nil {
|
||||
tags = make([]string, len(fields))
|
||||
}
|
||||
if tags != nil {
|
||||
tags = append(tags, tag)
|
||||
}
|
||||
|
||||
name := ident.Name
|
||||
fld := NewField(pos, check.pkg, name, typ, anonymous)
|
||||
// spec: "Within a struct, non-blank field names must be unique."
|
||||
if name == "_" || check.declareInSet(&fset, pos, fld) {
|
||||
fields = append(fields, fld)
|
||||
check.recordDef(ident, fld)
|
||||
}
|
||||
}
|
||||
|
||||
for _, f := range list.List {
|
||||
typ = check.typExpr(f.Type, nil, path)
|
||||
tag = check.tag(f.Tag)
|
||||
if len(f.Names) > 0 {
|
||||
// named fields
|
||||
for _, name := range f.Names {
|
||||
add(name, false, name.Pos())
|
||||
}
|
||||
} else {
|
||||
// anonymous field
|
||||
// spec: "An embedded type must be specified as a type name T or as a pointer
|
||||
// to a non-interface type name *T, and T itself may not be a pointer type."
|
||||
pos := f.Type.Pos()
|
||||
name := anonymousFieldIdent(f.Type)
|
||||
if name == nil {
|
||||
check.invalidAST(pos, "anonymous field type %s has no name", f.Type)
|
||||
continue
|
||||
}
|
||||
t, isPtr := deref(typ)
|
||||
// Because we have a name, typ must be of the form T or *T, where T is the name
|
||||
// of a (named or alias) type, and t (= deref(typ)) must be the type of T.
|
||||
switch t := t.Underlying().(type) {
|
||||
case *Basic:
|
||||
if t == Typ[Invalid] {
|
||||
// error was reported before
|
||||
continue
|
||||
}
|
||||
|
||||
// unsafe.Pointer is treated like a regular pointer
|
||||
if t.kind == UnsafePointer {
|
||||
check.errorf(pos, "anonymous field type cannot be unsafe.Pointer")
|
||||
continue
|
||||
}
|
||||
|
||||
case *Pointer:
|
||||
check.errorf(pos, "anonymous field type cannot be a pointer")
|
||||
continue
|
||||
|
||||
case *Interface:
|
||||
if isPtr {
|
||||
check.errorf(pos, "anonymous field type cannot be a pointer to an interface")
|
||||
continue
|
||||
}
|
||||
}
|
||||
add(name, true, pos)
|
||||
}
|
||||
}
|
||||
|
||||
styp.fields = fields
|
||||
styp.tags = tags
|
||||
}
|
||||
|
||||
func anonymousFieldIdent(e ast.Expr) *ast.Ident {
|
||||
switch e := e.(type) {
|
||||
case *ast.Ident:
|
||||
return e
|
||||
case *ast.StarExpr:
|
||||
// *T is valid, but **T is not
|
||||
if _, ok := e.X.(*ast.StarExpr); !ok {
|
||||
return anonymousFieldIdent(e.X)
|
||||
}
|
||||
case *ast.SelectorExpr:
|
||||
return e.Sel
|
||||
}
|
||||
return nil // invalid anonymous field
|
||||
}
|
229
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/universe.go
generated
vendored
229
vendor/k8s.io/kubernetes/third_party/forked/golang/go/types/universe.go
generated
vendored
@ -1,229 +0,0 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file sets up the universe scope and the unsafe package.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
Universe *Scope
|
||||
Unsafe *Package
|
||||
universeIota *Const
|
||||
universeByte *Basic // uint8 alias, but has name "byte"
|
||||
universeRune *Basic // int32 alias, but has name "rune"
|
||||
)
|
||||
|
||||
// Typ contains the predeclared *Basic types indexed by their
|
||||
// corresponding BasicKind.
|
||||
//
|
||||
// The *Basic type for Typ[Byte] will have the name "uint8".
|
||||
// Use Universe.Lookup("byte").Type() to obtain the specific
|
||||
// alias basic type named "byte" (and analogous for "rune").
|
||||
var Typ = []*Basic{
|
||||
Invalid: {Invalid, 0, "invalid type"},
|
||||
|
||||
Bool: {Bool, IsBoolean, "bool"},
|
||||
Int: {Int, IsInteger, "int"},
|
||||
Int8: {Int8, IsInteger, "int8"},
|
||||
Int16: {Int16, IsInteger, "int16"},
|
||||
Int32: {Int32, IsInteger, "int32"},
|
||||
Int64: {Int64, IsInteger, "int64"},
|
||||
Uint: {Uint, IsInteger | IsUnsigned, "uint"},
|
||||
Uint8: {Uint8, IsInteger | IsUnsigned, "uint8"},
|
||||
Uint16: {Uint16, IsInteger | IsUnsigned, "uint16"},
|
||||
Uint32: {Uint32, IsInteger | IsUnsigned, "uint32"},
|
||||
Uint64: {Uint64, IsInteger | IsUnsigned, "uint64"},
|
||||
Uintptr: {Uintptr, IsInteger | IsUnsigned, "uintptr"},
|
||||
Float32: {Float32, IsFloat, "float32"},
|
||||
Float64: {Float64, IsFloat, "float64"},
|
||||
Complex64: {Complex64, IsComplex, "complex64"},
|
||||
Complex128: {Complex128, IsComplex, "complex128"},
|
||||
String: {String, IsString, "string"},
|
||||
UnsafePointer: {UnsafePointer, 0, "Pointer"},
|
||||
|
||||
UntypedBool: {UntypedBool, IsBoolean | IsUntyped, "untyped bool"},
|
||||
UntypedInt: {UntypedInt, IsInteger | IsUntyped, "untyped int"},
|
||||
UntypedRune: {UntypedRune, IsInteger | IsUntyped, "untyped rune"},
|
||||
UntypedFloat: {UntypedFloat, IsFloat | IsUntyped, "untyped float"},
|
||||
UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, "untyped complex"},
|
||||
UntypedString: {UntypedString, IsString | IsUntyped, "untyped string"},
|
||||
UntypedNil: {UntypedNil, IsUntyped, "untyped nil"},
|
||||
}
|
||||
|
||||
var aliases = [...]*Basic{
|
||||
{Byte, IsInteger | IsUnsigned, "byte"},
|
||||
{Rune, IsInteger, "rune"},
|
||||
}
|
||||
|
||||
func defPredeclaredTypes() {
|
||||
for _, t := range Typ {
|
||||
def(NewTypeName(token.NoPos, nil, t.name, t))
|
||||
}
|
||||
for _, t := range aliases {
|
||||
def(NewTypeName(token.NoPos, nil, t.name, t))
|
||||
}
|
||||
|
||||
// Error has a nil package in its qualified name since it is in no package
|
||||
res := NewVar(token.NoPos, nil, "", Typ[String])
|
||||
sig := &Signature{results: NewTuple(res)}
|
||||
err := NewFunc(token.NoPos, nil, "Error", sig)
|
||||
typ := &Named{underlying: NewInterface([]*Func{err}, nil).Complete()}
|
||||
sig.recv = NewVar(token.NoPos, nil, "", typ)
|
||||
def(NewTypeName(token.NoPos, nil, "error", typ))
|
||||
}
|
||||
|
||||
var predeclaredConsts = [...]struct {
|
||||
name string
|
||||
kind BasicKind
|
||||
val constant.Value
|
||||
}{
|
||||
{"true", UntypedBool, constant.MakeBool(true)},
|
||||
{"false", UntypedBool, constant.MakeBool(false)},
|
||||
{"iota", UntypedInt, constant.MakeInt64(0)},
|
||||
}
|
||||
|
||||
func defPredeclaredConsts() {
|
||||
for _, c := range predeclaredConsts {
|
||||
def(NewConst(token.NoPos, nil, c.name, Typ[c.kind], c.val))
|
||||
}
|
||||
}
|
||||
|
||||
func defPredeclaredNil() {
|
||||
def(&Nil{object{name: "nil", typ: Typ[UntypedNil]}})
|
||||
}
|
||||
|
||||
// A builtinId is the id of a builtin function.
|
||||
type builtinId int
|
||||
|
||||
const (
|
||||
// universe scope
|
||||
_Append builtinId = iota
|
||||
_Cap
|
||||
_Close
|
||||
_Complex
|
||||
_Copy
|
||||
_Delete
|
||||
_Imag
|
||||
_Len
|
||||
_Make
|
||||
_New
|
||||
_Panic
|
||||
_Print
|
||||
_Println
|
||||
_Real
|
||||
_Recover
|
||||
|
||||
// package unsafe
|
||||
_Alignof
|
||||
_Offsetof
|
||||
_Sizeof
|
||||
|
||||
// testing support
|
||||
_Assert
|
||||
_Trace
|
||||
)
|
||||
|
||||
var predeclaredFuncs = [...]struct {
|
||||
name string
|
||||
nargs int
|
||||
variadic bool
|
||||
kind exprKind
|
||||
}{
|
||||
_Append: {"append", 1, true, expression},
|
||||
_Cap: {"cap", 1, false, expression},
|
||||
_Close: {"close", 1, false, statement},
|
||||
_Complex: {"complex", 2, false, expression},
|
||||
_Copy: {"copy", 2, false, statement},
|
||||
_Delete: {"delete", 2, false, statement},
|
||||
_Imag: {"imag", 1, false, expression},
|
||||
_Len: {"len", 1, false, expression},
|
||||
_Make: {"make", 1, true, expression},
|
||||
_New: {"new", 1, false, expression},
|
||||
_Panic: {"panic", 1, false, statement},
|
||||
_Print: {"print", 0, true, statement},
|
||||
_Println: {"println", 0, true, statement},
|
||||
_Real: {"real", 1, false, expression},
|
||||
_Recover: {"recover", 0, false, statement},
|
||||
|
||||
_Alignof: {"Alignof", 1, false, expression},
|
||||
_Offsetof: {"Offsetof", 1, false, expression},
|
||||
_Sizeof: {"Sizeof", 1, false, expression},
|
||||
|
||||
_Assert: {"assert", 1, false, statement},
|
||||
_Trace: {"trace", 0, true, statement},
|
||||
}
|
||||
|
||||
func defPredeclaredFuncs() {
|
||||
for i := range predeclaredFuncs {
|
||||
id := builtinId(i)
|
||||
if id == _Assert || id == _Trace {
|
||||
continue // only define these in testing environment
|
||||
}
|
||||
def(newBuiltin(id))
|
||||
}
|
||||
}
|
||||
|
||||
// DefPredeclaredTestFuncs defines the assert and trace built-ins.
|
||||
// These built-ins are intended for debugging and testing of this
|
||||
// package only.
|
||||
func DefPredeclaredTestFuncs() {
|
||||
if Universe.Lookup("assert") != nil {
|
||||
return // already defined
|
||||
}
|
||||
def(newBuiltin(_Assert))
|
||||
def(newBuiltin(_Trace))
|
||||
}
|
||||
|
||||
func init() {
|
||||
Universe = NewScope(nil, token.NoPos, token.NoPos, "universe")
|
||||
Unsafe = NewPackage("unsafe", "unsafe")
|
||||
Unsafe.complete = true
|
||||
|
||||
defPredeclaredTypes()
|
||||
defPredeclaredConsts()
|
||||
defPredeclaredNil()
|
||||
defPredeclaredFuncs()
|
||||
|
||||
universeIota = Universe.Lookup("iota").(*Const)
|
||||
universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
|
||||
universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
|
||||
}
|
||||
|
||||
// Objects with names containing blanks are internal and not entered into
|
||||
// a scope. Objects with exported names are inserted in the unsafe package
|
||||
// scope; other objects are inserted in the universe scope.
|
||||
//
|
||||
func def(obj Object) {
|
||||
name := obj.Name()
|
||||
if strings.Contains(name, " ") {
|
||||
return // nothing to do
|
||||
}
|
||||
// fix Obj link for named types
|
||||
if typ, ok := obj.Type().(*Named); ok {
|
||||
typ.obj = obj.(*TypeName)
|
||||
}
|
||||
// exported identifiers go into package unsafe
|
||||
scope := Universe
|
||||
if obj.Exported() {
|
||||
scope = Unsafe.scope
|
||||
// set Pkg field
|
||||
switch obj := obj.(type) {
|
||||
case *TypeName:
|
||||
obj.pkg = Unsafe
|
||||
case *Builtin:
|
||||
obj.pkg = Unsafe
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
}
|
||||
if scope.Insert(obj) != nil {
|
||||
panic("internal error: double declaration")
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user