From 0fd48a9faea7cc09ec866a6b79233e209085c703 Mon Sep 17 00:00:00 2001 From: Adrian Riobo Date: Fri, 9 Jan 2026 12:39:37 +0100 Subject: [PATCH] fix(deps): update all dependencies --- Makefile | 2 +- go.mod | 10 +- go.sum | 20 +- oci/Containerfile | 8 +- tools/go.mod | 26 +- tools/go.sum | 42 +- .../polyfloyd/go-errorlint/LICENSE | 0 .../go-errorlint/errorlint/allowed.go | 0 .../go-errorlint/errorlint/analysis.go | 0 .../polyfloyd/go-errorlint/errorlint/lint.go | 194 +++-- .../go-errorlint/errorlint/options.go | 12 + .../go-errorlint/errorlint/printf.go | 0 .../github.com/MirrexOne/unqueryvet/README.md | 137 +++- .../unqueryvet/internal/analyzer/analyzer.go | 102 ++- .../unqueryvet/internal/analyzer/concat.go | 100 +++ .../unqueryvet/internal/analyzer/filter.go | 176 +++++ .../unqueryvet/internal/analyzer/fixes.go | 126 +++ .../unqueryvet/internal/analyzer/format.go | 217 ++++++ .../internal/analyzer/sqlbuilders/bun.go | 156 ++++ .../internal/analyzer/sqlbuilders/ent.go | 95 +++ .../internal/analyzer/sqlbuilders/gorm.go | 201 +++++ .../analyzer/sqlbuilders/interface.go | 107 +++ .../internal/analyzer/sqlbuilders/jet.go | 192 +++++ .../internal/analyzer/sqlbuilders/pgx.go | 94 +++ .../analyzer/sqlbuilders/sqlboiler.go | 144 ++++ .../internal/analyzer/sqlbuilders/sqlx.go | 100 +++ .../internal/analyzer/sqlbuilders/squirrel.go | 190 +++++ .../MirrexOne/unqueryvet/pkg/config/config.go | 84 +- .../alexkohler/prealloc/pkg/math.go | 117 +++ .../alexkohler/prealloc/pkg/prealloc.go | 735 +++++++++++++----- .../alexkohler/prealloc/pkg/types.go | 376 +++++++++ .../go-critic/checkers/embedded_rules.go | 64 +- .../godoc-lint/pkg/check/max_len/max_len.go | 66 +- .../godoc-lint/pkg/check/registry.go | 2 + .../pkg/check/require_doc/require_doc.go | 6 + .../check/start_with_name/start_with_name.go | 6 + .../pkg/check/stdlib_doclink/data.go | 27 + .../pkg/check/stdlib_doclink/internal/type.go | 30 + .../pkg/check/stdlib_doclink/stdlib.json | 1 + .../check/stdlib_doclink/stdlib_doclink.go | 319 ++++++++ .../godoc-lint/pkg/config/builder.go | 42 +- .../godoc-lint/pkg/config/default.yaml | 2 + .../godoc-lint/pkg/config/parser.go | 2 +- .../godoc-lint/godoc-lint/pkg/config/plain.go | 68 +- .../godoc-lint/pkg/inspect/inspector.go | 38 +- .../godoc-lint/godoc-lint/pkg/model/config.go | 24 +- .../godoc-lint/pkg/model/inspector.go | 30 +- .../godoc-lint/godoc-lint/pkg/model/rule.go | 3 + .../v2/pkg/config/linters_settings.go | 40 +- .../v2/pkg/goformatters/golines/golines.go | 28 +- .../v2/pkg/golinters/errorlint/errorlint.go | 2 +- .../v2/pkg/golinters/godoclint/godoclint.go | 32 +- .../gomoddirectives/gomoddirectives.go | 1 + .../v2/pkg/golinters/modernize/modernize.go | 20 +- .../v2/pkg/golinters/prealloc/prealloc.go | 8 +- .../v2/pkg/golinters/revive/revive.go | 19 +- .../v2/pkg/golinters/unqueryvet/unqueryvet.go | 19 + .../v2/pkg/lint/lintersdb/builder_linter.go | 2 +- .../golangci/golines/.gitattributes | 1 - .../github.com/golangci/golines/.gitignore | 20 - .../github.com/golangci/golines/README.md | 30 - .../github.com/golangci/golines/annotation.go | 99 --- .../golangci/golines/shorten/.gitattributes | 3 + .../golangci/golines/shorten/annotations.go | 65 ++ .../golangci/golines/shorten/format.go | 339 ++++++++ .../shorten/internal/annotation/annotation.go | 91 +++ .../shorten/internal/comments/comments.go | 104 +++ .../golines/shorten/internal/graph/graph.go | 132 ++++ .../shorten/internal/graph/graph_generated.go | 596 ++++++++++++++ .../golangci/golines/shorten/internal/line.go | 16 + .../golines/shorten/internal/tags/filler.go | 42 + .../{ => shorten/internal/tags}/tags.go | 123 +-- .../golangci/golines/shorten/log.go | 9 + .../golangci/golines/shorten/shortener.go | 206 +++++ .../github.com/golangci/golines/shortener.go | 594 -------------- .../vendor/github.com/ldez/structtags/LICENSE | 674 ++++++++++++++++ .../github.com/ldez/structtags/parser/tag.go | 115 +++ .../ldez/structtags/parser/value.go | 83 ++ .../github.com/nunnatsa/ginkgolinter/Makefile | 6 + .../internal/expression/actual/actual.go | 13 +- .../internal/expression/actual/actualarg.go | 15 +- .../internal/expression/expression.go | 54 +- .../internal/expression/matcher/matcher.go | 15 +- .../expression/matcher/matcherinfo.go | 8 +- .../expression/matcher/matcherwithnest.go | 4 +- .../expression/matcher/multiplematchers.go | 12 +- .../internal/gomegahandler/dothandler.go | 109 --- .../internal/gomegahandler/handler.go | 276 ++++++- .../internal/gomegahandler/namedhandler.go | 123 --- .../internal/gomegainfo/gomegainfo.go | 23 +- .../internal/intervals/intervals.go | 204 ++++- .../internal/rules/asynctimeintervalsrule.go | 2 +- .../internal/rules/missingassertionrule.go | 12 +- .../ginkgolinter/linter/ginkgo_linter.go | 7 +- .../arangolint/pkg/analyzer/analyzer.go | 530 ++++++++++++- tools/vendor/modules.txt | 43 +- vendor/github.com/pulumi/esc/.version | 2 +- vendor/github.com/pulumi/esc/CHANGELOG.md | 18 +- .../pulumi/esc/CHANGELOG_PENDING.md | 11 +- vendor/github.com/pulumi/esc/ast/expr.go | 37 + vendor/github.com/pulumi/esc/eval/crypt.go | 36 +- vendor/github.com/pulumi/esc/eval/eval.go | 32 + vendor/github.com/pulumi/esc/eval/expr.go | 23 + vendor/github.com/pulumi/esc/eval/patch.go | 74 +- .../sdk/go/aws/internal/pulumiUtilities.go | 4 +- .../sdk/go/aws/pulumi-plugin.json | 2 +- .../v4/go/docker/internal/pulumiUtilities.go | 4 +- .../sdk/v4/go/docker/pulumi-plugin.json | 2 +- .../sdk/v4/go/docker/pulumiTypes.go | 34 +- .../github.com/pulumi/pulumi/sdk/v3/.version | 2 +- .../sdk/v3/go/common/resource/config/value.go | 10 +- .../v3/go/common/resource/plugin/analyzer.go | 3 +- .../common/resource/plugin/analyzer_plugin.go | 16 +- .../v3/go/common/resource/plugin/context.go | 43 +- .../sdk/v3/go/common/resource/plugin/host.go | 78 +- .../go/common/resource/plugin/langruntime.go | 2 +- .../resource/plugin/langruntime_plugin.go | 17 +- .../sdk/v3/go/common/resource/plugin/mock.go | 18 +- .../v3/go/common/resource/plugin/plugin.go | 38 +- .../go/common/resource/plugin/plugin_info.go | 25 + .../v3/go/common/resource/plugin/provider.go | 13 +- .../common/resource/plugin/provider_plugin.go | 34 +- .../common/resource/plugin/provider_server.go | 3 +- .../resource/plugin/provider_unimplemented.go | 5 +- .../sdk/v3/go/common/workspace/plugins.go | 69 +- .../sdk/v3/go/common/workspace/project.go | 11 +- .../sdk/v3/go/common/workspace/project.json | 11 + .../pulumi/sdk/v3/proto/go/provider.pb.go | 27 +- .../sdk/v3/proto/go/provider_grpc.pb.go | 2 +- vendor/golang.org/x/sys/cpu/cpu_x86.go | 174 +++-- vendor/modules.txt | 14 +- 131 files changed, 8384 insertions(+), 1972 deletions(-) rename tools/vendor/{github.com => codeberg.org}/polyfloyd/go-errorlint/LICENSE (100%) rename tools/vendor/{github.com => codeberg.org}/polyfloyd/go-errorlint/errorlint/allowed.go (100%) rename tools/vendor/{github.com => codeberg.org}/polyfloyd/go-errorlint/errorlint/analysis.go (100%) rename tools/vendor/{github.com => codeberg.org}/polyfloyd/go-errorlint/errorlint/lint.go (87%) rename tools/vendor/{github.com => codeberg.org}/polyfloyd/go-errorlint/errorlint/options.go (56%) rename tools/vendor/{github.com => codeberg.org}/polyfloyd/go-errorlint/errorlint/printf.go (100%) create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/concat.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/filter.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/fixes.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/format.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/bun.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/ent.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/gorm.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/interface.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/jet.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/pgx.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/sqlboiler.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/sqlx.go create mode 100644 tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/squirrel.go create mode 100644 tools/vendor/github.com/alexkohler/prealloc/pkg/math.go create mode 100644 tools/vendor/github.com/alexkohler/prealloc/pkg/types.go create mode 100644 tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/data.go create mode 100644 tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/internal/type.go create mode 100644 tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/stdlib.json create mode 100644 tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/stdlib_doclink.go delete mode 100644 tools/vendor/github.com/golangci/golines/.gitattributes delete mode 100644 tools/vendor/github.com/golangci/golines/.gitignore delete mode 100644 tools/vendor/github.com/golangci/golines/README.md delete mode 100644 tools/vendor/github.com/golangci/golines/annotation.go create mode 100644 tools/vendor/github.com/golangci/golines/shorten/.gitattributes create mode 100644 tools/vendor/github.com/golangci/golines/shorten/annotations.go create mode 100644 tools/vendor/github.com/golangci/golines/shorten/format.go create mode 100644 tools/vendor/github.com/golangci/golines/shorten/internal/annotation/annotation.go create mode 100644 tools/vendor/github.com/golangci/golines/shorten/internal/comments/comments.go create mode 100644 tools/vendor/github.com/golangci/golines/shorten/internal/graph/graph.go create mode 100644 tools/vendor/github.com/golangci/golines/shorten/internal/graph/graph_generated.go create mode 100644 tools/vendor/github.com/golangci/golines/shorten/internal/line.go create mode 100644 tools/vendor/github.com/golangci/golines/shorten/internal/tags/filler.go rename tools/vendor/github.com/golangci/golines/{ => shorten/internal/tags}/tags.go (59%) create mode 100644 tools/vendor/github.com/golangci/golines/shorten/log.go create mode 100644 tools/vendor/github.com/golangci/golines/shorten/shortener.go delete mode 100644 tools/vendor/github.com/golangci/golines/shortener.go create mode 100644 tools/vendor/github.com/ldez/structtags/LICENSE create mode 100644 tools/vendor/github.com/ldez/structtags/parser/tag.go create mode 100644 tools/vendor/github.com/ldez/structtags/parser/value.go delete mode 100644 tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/dothandler.go delete mode 100644 tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/namedhandler.go create mode 100644 vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/plugin_info.go diff --git a/Makefile b/Makefile index 4aff22e60..c895cdb85 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ TKN_IMG ?= quay.io/redhat-developer/mapt:v${VERSION}-tkn # Integrations # renovate: datasource=github-releases depName=cirruslabs/cirrus-cli -CIRRUS_CLI ?= v0.158.0 +CIRRUS_CLI ?= v0.159.1 # renovate: datasource=github-releases depName=actions/runner GITHUB_RUNNER ?= 2.330.0 diff --git a/go.mod b/go.mod index ff5816f31..6daaa9727 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/coocood/freecache v1.2.4 github.com/pulumi/pulumi-command/sdk v1.1.3 github.com/pulumi/pulumi-random/sdk/v4 v4.18.4 - github.com/pulumi/pulumi/sdk/v3 v3.213.0 + github.com/pulumi/pulumi/sdk/v3 v3.215.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.10.2 ) @@ -23,7 +23,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ec2 v1.279.0 github.com/aws/aws-sdk-go-v2/service/s3 v1.95.0 github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 - github.com/pulumi/pulumi-aws-native/sdk v1.45.0 + github.com/pulumi/pulumi-aws-native/sdk v1.47.0 github.com/pulumi/pulumi-aws/sdk/v7 v7.15.0 github.com/pulumi/pulumi-awsx/sdk/v3 v3.1.0 github.com/pulumi/pulumi-azure-native-sdk/authorization/v3 v3.12.0 @@ -44,7 +44,7 @@ require ( github.com/leodido/go-urn v1.4.0 // indirect github.com/pgavlin/fx/v2 v2.0.12 // indirect github.com/pulumi/pulumi-azure-native-sdk/v3 v3.12.0 // indirect - github.com/pulumi/pulumi-docker/sdk/v4 v4.10.0 // indirect + github.com/pulumi/pulumi-docker/sdk/v4 v4.11.0 // indirect ) require ( @@ -121,7 +121,7 @@ require ( github.com/pjbgf/sha1cd v0.5.0 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231 // indirect - github.com/pulumi/esc v0.20.0 // indirect + github.com/pulumi/esc v0.21.0 // indirect github.com/pulumi/pulumi-docker-build/sdk/go/dockerbuild v0.0.15 // indirect github.com/sagikazarmark/locafero v0.12.0 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect @@ -180,7 +180,7 @@ require ( go.uber.org/atomic v1.11.0 // indirect golang.org/x/crypto v0.46.0 // indirect golang.org/x/net v0.48.0 // indirect - golang.org/x/sys v0.39.0 // indirect + golang.org/x/sys v0.40.0 // indirect golang.org/x/term v0.38.0 // indirect golang.org/x/text v0.32.0 // indirect google.golang.org/grpc v1.78.0 // indirect diff --git a/go.sum b/go.sum index 63c19a5ec..4ea6673f1 100644 --- a/go.sum +++ b/go.sum @@ -298,10 +298,10 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231 h1:vkHw5I/plNdTr435cARxCW6q9gc0S/Yxz7Mkd38pOb0= github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231/go.mod h1:murToZ2N9hNJzewjHBgfFdXhZKjY3z5cYC1VXk+lbFE= -github.com/pulumi/esc v0.20.0 h1:LZn4sjAsI76x10ZuZXXyh2ExGcP7AHmjOzCi/p3/fpQ= -github.com/pulumi/esc v0.20.0/go.mod h1:h1VjdedI0K84MhMzaR9ZKbEpU6SfZMOZF4ZrVgQyNLY= -github.com/pulumi/pulumi-aws-native/sdk v1.45.0 h1:pJSnrrtgjpbpsga+KcEDDwLe/tMpxZz0a+rWy+GsK3E= -github.com/pulumi/pulumi-aws-native/sdk v1.45.0/go.mod h1:gmgSOTrjC7wArS3etY/n8vcEvDF56AQenP8YSH9tlII= +github.com/pulumi/esc v0.21.0 h1:TR8Ff22SU+z8cooTmUKkmk2FltXW/wDPrIwI9BP88Vk= +github.com/pulumi/esc v0.21.0/go.mod h1:mkghIFn/TvN3XnP4jmCB4U5BG1I4UjGluARi39ckrCE= +github.com/pulumi/pulumi-aws-native/sdk v1.47.0 h1:4CVeLZFGsgx+yWTaRxBDVdqRtjf5tpe+JFqe0xugsn0= +github.com/pulumi/pulumi-aws-native/sdk v1.47.0/go.mod h1:gmgSOTrjC7wArS3etY/n8vcEvDF56AQenP8YSH9tlII= github.com/pulumi/pulumi-aws/sdk/v7 v7.15.0 h1:6Ae7ZU+xmXhYN8KDitJdnv3hojogvurm5D5IbjQIeBw= github.com/pulumi/pulumi-aws/sdk/v7 v7.15.0/go.mod h1:hsOxQjCl7ASsYWRVC8UtbFaR+xx9S0QwNFnbo0Kzg1I= github.com/pulumi/pulumi-awsx/sdk/v3 v3.1.0 h1:jphjwZoSnNyW4d3dpS++T+TlZFTy6vb9gJt33u6xf14= @@ -326,16 +326,16 @@ github.com/pulumi/pulumi-command/sdk v1.1.3 h1:2FdcqVenuHcGJfcVnUg6G22IeoQ/lY5UX github.com/pulumi/pulumi-command/sdk v1.1.3/go.mod h1:3ochnip+NSR3+lQh8//Cni6hR9ckswuc1c6URsmX4RM= github.com/pulumi/pulumi-docker-build/sdk/go/dockerbuild v0.0.15 h1:K6F/3o44gGj+ljRS4spCGvAXMSwECHITjaCccfjXNyE= github.com/pulumi/pulumi-docker-build/sdk/go/dockerbuild v0.0.15/go.mod h1:cZyHs6q34kbQZJYaBjWUJhPsgwUFoL6xyjo7sRqBcv4= -github.com/pulumi/pulumi-docker/sdk/v4 v4.10.0 h1:nEMfHqLDN5D4xr4xZutNItASHy3rns/mTdtm0pTIp58= -github.com/pulumi/pulumi-docker/sdk/v4 v4.10.0/go.mod h1:iNOVp0nr1rRLTwH+pWZqbKaagjoVgYpqGibsmHmk6u4= +github.com/pulumi/pulumi-docker/sdk/v4 v4.11.0 h1:I8nJlJcQQiMs0njR1/CvXWk2y0dzhwSXIW62xuVaZQc= +github.com/pulumi/pulumi-docker/sdk/v4 v4.11.0/go.mod h1:TbjBDNYFkMGmDZdrV6grRy+7AADkGLTcPjLHY9gh8dg= github.com/pulumi/pulumi-kubernetes/sdk/v4 v4.24.1 h1:L1J2/PHgAziDXUvOWJ4HH1JBlgxzpQseZiEIu4K2x34= github.com/pulumi/pulumi-kubernetes/sdk/v4 v4.24.1/go.mod h1:vNiMC/N8GNHvDwU3gQRXQ6V+kbgSl5N/lKtfrUjGuXU= github.com/pulumi/pulumi-random/sdk/v4 v4.18.4 h1:mkZ3nB3xLTFZ8Fbh50bXTxiroGpjSyonTFcKovLxWME= github.com/pulumi/pulumi-random/sdk/v4 v4.18.4/go.mod h1:BBVUyqFkhCbwvUSnDjubH5b+SeJeoMQH4COGNKaaoUI= github.com/pulumi/pulumi-tls/sdk/v5 v5.2.3 h1:HEHeifaSKme+mWXYkps5qYD45JJc86Y/0awBj7UC6vU= github.com/pulumi/pulumi-tls/sdk/v5 v5.2.3/go.mod h1:UxIBAyqaLIo5bn63paPM7FU7DahbfeSIKbgTf9KldLY= -github.com/pulumi/pulumi/sdk/v3 v3.213.0 h1:ICp0WJlTShaTLrx2fDI52fJ3xwCf1h8T8tVrKDRNUB4= -github.com/pulumi/pulumi/sdk/v3 v3.213.0/go.mod h1:Bn5Z9Rzp1lPqdAccaB+F2ivUBiamEl2TNR3Gg/h7iLs= +github.com/pulumi/pulumi/sdk/v3 v3.215.0 h1:XZMiv9aSE1pD3kW4JpA53cy7mFflbJYn1fFKH1NMIAY= +github.com/pulumi/pulumi/sdk/v3 v3.215.0/go.mod h1:Bn5Z9Rzp1lPqdAccaB+F2ivUBiamEl2TNR3Gg/h7iLs= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= @@ -457,8 +457,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= diff --git a/oci/Containerfile b/oci/Containerfile index f200d4dc8..677ba530c 100644 --- a/oci/Containerfile +++ b/oci/Containerfile @@ -1,12 +1,12 @@ -FROM registry.access.redhat.com/ubi9/go-toolset@sha256:20b655db80d929d3a3828947d718746f0aee3159c86620df330e58cbf954970e as builder +FROM registry.access.redhat.com/ubi9/go-toolset@sha256:38d909b4f0b5244bc6dffab499fa3324e2ce878dcc79e3ee85a200655cbba736 as builder ARG TARGETARCH USER root WORKDIR /workspace COPY . . # renovate: datasource=github-releases depName=pulumi/pulumi -ENV PULUMI_VERSION 3.213.0 +ENV PULUMI_VERSION 3.215.0 ENV PULUMI_BASE_URL="https://github.com/pulumi/pulumi/releases/download/v${PULUMI_VERSION}/pulumi-v${PULUMI_VERSION}" ENV PULUMI_URL="${PULUMI_BASE_URL}-linux-x64.tar.gz" @@ -19,7 +19,7 @@ RUN unset VERSION \ && tar -xzvf pulumicli.tar.gz # ubi 9.5-1732804088 -FROM registry.access.redhat.com/ubi9/ubi@sha256:3816d303e75dec4da2d10eeb9e8651eef4393721598bea4690c607282635aa57 +FROM registry.access.redhat.com/ubi9/ubi@sha256:2c9bb68a869abf7d7417f6639509ab5eb8500d8429ea11ab59e677be5545162b ARG TARGETARCH LABEL org.opencontainers.image.authors="Redhat Developer" @@ -44,7 +44,7 @@ ARG PULUMI_TLS_VERSION=v5.2.3 # renovate: datasource=github-releases depName=pulumi/pulumi-random ARG PULUMI_RANDOM_VERSION=v4.18.4 # renovate: datasource=github-releases depName=pulumi/pulumi-aws-native -ARG PULUMI_AWS_NATIVE_VERSION=v1.45.0 +ARG PULUMI_AWS_NATIVE_VERSION=v1.47.0 ENV PULUMI_HOME "/opt/mapt/run" WORKDIR ${PULUMI_HOME} diff --git a/tools/go.mod b/tools/go.mod index 5e31b464d..02574d8da 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -2,12 +2,12 @@ module github.com/redhat-developer/mapt/tools go 1.24.6 -require github.com/golangci/golangci-lint/v2 v2.7.2 +require github.com/golangci/golangci-lint/v2 v2.8.0 require ( github.com/charmbracelet/x/cellbuf v0.0.14 // indirect - github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect - github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 // indirect + // github.com/golangci/gofmt e7be49a5ab4d // indirect + github.com/golangci/golines v0.14.0 // indirect ) require ( @@ -22,19 +22,21 @@ require ( dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect dev.gaijin.team/go/golib v0.8.0 // indirect github.com/AdminBenni/iota-mixing v1.0.0 // indirect - github.com/MirrexOne/unqueryvet v1.3.0 // indirect + github.com/MirrexOne/unqueryvet v1.4.0 // indirect github.com/alfatraining/structtag v1.0.0 // indirect github.com/clipperhouse/uax29/v2 v2.3.0 // indirect - github.com/godoc-lint/godoc-lint v0.10.2 // indirect + github.com/godoc-lint/godoc-lint v0.11.1 // indirect github.com/golangci/asciicheck v0.5.0 // indirect github.com/gostaticanalysis/nilerr v0.1.2 // indirect - github.com/nunnatsa/ginkgolinter v0.21.2 // indirect + github.com/nunnatsa/ginkgolinter v0.22.0 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect ) require ( 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect codeberg.org/chavacava/garif v0.2.0 // indirect + codeberg.org/polyfloyd/go-errorlint v1.9.0 // indirect github.com/4meepo/tagalign v1.4.3 // indirect github.com/Abirdcfly/dupword v0.1.7 // indirect github.com/AlwxSin/noinlineerr v1.0.5 // indirect @@ -48,7 +50,7 @@ require ( github.com/alecthomas/chroma/v2 v2.21.1 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect github.com/alexkohler/nakedret/v2 v2.0.6 // indirect - github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alexkohler/prealloc v1.0.1 // indirect github.com/alingse/asasalint v0.0.11 // indirect github.com/alingse/nilnesserr v0.2.0 // indirect github.com/ashanbrown/forbidigo/v2 v2.3.0 // indirect @@ -84,7 +86,7 @@ require ( github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect github.com/ghostiam/protogetter v0.3.18 // indirect - github.com/go-critic/go-critic v0.14.2 // indirect + github.com/go-critic/go-critic v0.14.3 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect github.com/go-toolsmith/astequal v1.2.0 // indirect @@ -98,6 +100,7 @@ require ( github.com/gofrs/flock v0.13.0 // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect github.com/golangci/go-printf-func-name v0.1.1 // indirect + github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect github.com/golangci/misspell v0.7.0 // indirect github.com/golangci/plugin-module-register v0.1.2 // indirect github.com/golangci/revgrep v0.8.0 // indirect @@ -126,6 +129,7 @@ require ( github.com/ldez/exptostd v0.4.5 // indirect github.com/ldez/gomoddirectives v0.8.0 // indirect github.com/ldez/grignotin v0.10.1 // indirect + github.com/ldez/structtags v0.6.1 // indirect github.com/ldez/tagliatelle v0.7.2 // indirect github.com/ldez/usetesting v0.5.0 // indirect github.com/leonklingele/grouper v1.1.2 // indirect @@ -149,7 +153,6 @@ require ( github.com/nishanths/predeclared v0.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.8.0 // indirect github.com/prometheus/client_golang v1.23.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.67.4 // indirect @@ -201,16 +204,15 @@ require ( gitlab.com/bosi/decorder v0.4.2 // indirect go-simpler.org/musttag v0.14.0 // indirect go-simpler.org/sloglint v0.11.1 // indirect - go.augendre.info/arangolint v0.3.1 // indirect + go.augendre.info/arangolint v0.4.0 // indirect go.augendre.info/fatcontext v0.9.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.1 // indirect - go.yaml.in/yaml/v2 v2.4.3 // indirect golang.org/x/exp/typeparams v0.0.0-20251219203646-944ab1f22d93 // indirect golang.org/x/mod v0.31.0 // indirect golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.39.0 // indirect + golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.32.0 // indirect golang.org/x/tools v0.40.0 // indirect google.golang.org/protobuf v1.36.11 // indirect diff --git a/tools/go.sum b/tools/go.sum index e6282520f..094363fac 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -4,6 +4,8 @@ 4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0= codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= +codeberg.org/polyfloyd/go-errorlint v1.9.0 h1:VkdEEmA1VBpH6ecQoMR4LdphVI3fA4RrCh2an7YmodI= +codeberg.org/polyfloyd/go-errorlint v1.9.0/go.mod h1:GPRRu2LzVijNn4YkrZYJfatQIdS+TrcK8rL5Xs24qw8= dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKfwODoI1Y= dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI= dev.gaijin.team/go/golib v0.8.0 h1:BiDNudpoFizoU5VHdQUiabtHSt9fyPX11Fr4OU9PaUQ= @@ -28,8 +30,8 @@ github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/MirrexOne/unqueryvet v1.3.0 h1:5slWSomgqpYU4zFuZ3NNOfOUxVPlXFDBPAVasZOGlAY= -github.com/MirrexOne/unqueryvet v1.3.0/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= +github.com/MirrexOne/unqueryvet v1.4.0 h1:6KAkqqW2KUnkl9Z0VuTphC3IXRPoFqEkJEtyxxHj5eQ= +github.com/MirrexOne/unqueryvet v1.4.0/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= @@ -42,8 +44,8 @@ github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQiFSsuzQ= github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= -github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= -github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alexkohler/prealloc v1.0.1 h1:A9P1haqowqUxWvU9nk6tQ7YktXIHf+LQM9wPRhuteEE= +github.com/alexkohler/prealloc v1.0.1/go.mod h1:fT39Jge3bQrfA7nPMDngUfvUbQGQeJyGQnR+913SCig= github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc= github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= @@ -132,8 +134,8 @@ github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghostiam/protogetter v0.3.18 h1:yEpghRGtP9PjKvVXtEzGpYfQj1Wl/ZehAfU6fr62Lfo= github.com/ghostiam/protogetter v0.3.18/go.mod h1:FjIu5Yfs6FT391m+Fjp3fbAYJ6rkL/J6ySpZBfnODuI= -github.com/go-critic/go-critic v0.14.2 h1:PMvP5f+LdR8p6B29npvChUXbD1vrNlKDf60NJtgMBOo= -github.com/go-critic/go-critic v0.14.2/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ= +github.com/go-critic/go-critic v0.14.3 h1:5R1qH2iFeo4I/RJU8vTezdqs08Egi4u5p6vOESA0pog= +github.com/go-critic/go-critic v0.14.3/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= @@ -165,8 +167,8 @@ github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUW github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/godoc-lint/godoc-lint v0.10.2 h1:dksNgK+zebnVlj4Fx83CRnCmPO0qRat/9xfFsir1nfg= -github.com/godoc-lint/godoc-lint v0.10.2/go.mod h1:KleLcHu/CGSvkjUH2RvZyoK1MBC7pDQg4NxMYLcBBsw= +github.com/godoc-lint/godoc-lint v0.11.1 h1:z9as8Qjiy6miRIa3VRymTa+Gt2RLnGICVikcvlUVOaA= +github.com/godoc-lint/godoc-lint v0.11.1/go.mod h1:BAqayheFSuZrEAqCRxgw9MyvsM+S/hZwJbU1s/ejRj8= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/golangci/asciicheck v0.5.0 h1:jczN/BorERZwK8oiFBOGvlGPknhvq0bjnysTj4nUfo0= @@ -177,10 +179,10 @@ github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarog github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint/v2 v2.7.2 h1:AhBC+YeEueec4AGlIbvPym5C70Thx0JykIqXbdIXWx0= -github.com/golangci/golangci-lint/v2 v2.7.2/go.mod h1:pDijleoBu7e8sejMqyZ3L5n6geqe+cVvOAz2QImqqVc= -github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 h1:AkK+w9FZBXlU/xUmBtSJN1+tAI4FIvy5WtnUnY8e4p8= -github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95/go.mod h1:k9mmcyWKSTMcPPvQUCfRWWQ9VHJ1U9Dc0R7kaXAgtnQ= +github.com/golangci/golangci-lint/v2 v2.8.0 h1:wJnr3hJWY3eVzOUcfwbDc2qbi2RDEpvLmQeNFaPSNYA= +github.com/golangci/golangci-lint/v2 v2.8.0/go.mod h1:xl+HafQ9xoP8rzw0z5AwnO5kynxtb80e8u02Ej/47RI= +github.com/golangci/golines v0.14.0 h1:xt9d3RKBjhasA3qpoXs99J2xN2t6eBlpLHt0TrgyyXc= +github.com/golangci/golines v0.14.0/go.mod h1:gf555vPG2Ia7mmy2mzmhVQbVjuK8Orw0maR1G4vVAAQ= github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= @@ -255,6 +257,8 @@ github.com/ldez/gomoddirectives v0.8.0 h1:JqIuTtgvFC2RdH1s357vrE23WJF2cpDCPFgA/T github.com/ldez/gomoddirectives v0.8.0/go.mod h1:jutzamvZR4XYJLr0d5Honycp4Gy6GEg2mS9+2YX3F1Q= github.com/ldez/grignotin v0.10.1 h1:keYi9rYsgbvqAZGI1liek5c+jv9UUjbvdj3Tbn5fn4o= github.com/ldez/grignotin v0.10.1/go.mod h1:UlDbXFCARrXbWGNGP3S5vsysNXAPhnSuBufpTEbwOas= +github.com/ldez/structtags v0.6.1 h1:bUooFLbXx41tW8SvkfwfFkkjPYvFFs59AAMgVg6DUBk= +github.com/ldez/structtags v0.6.1/go.mod h1:YDxVSgDy/MON6ariaxLF2X09bh19qL7MtGBN5MrvbdY= github.com/ldez/tagliatelle v0.7.2 h1:KuOlL70/fu9paxuxbeqlicJnCspCRjH0x8FW+NfgYUk= github.com/ldez/tagliatelle v0.7.2/go.mod h1:PtGgm163ZplJfZMZ2sf5nhUT170rSuPgBimoyYtdaSI= github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc= @@ -299,8 +303,8 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.21.2 h1:khzWfm2/Br8ZemX8QM1pl72LwM+rMeW6VUbQ4rzh0Po= -github.com/nunnatsa/ginkgolinter v0.21.2/go.mod h1:GItSI5fw7mCGLPmkvGYrr1kEetZe7B593jcyOpyabsY= +github.com/nunnatsa/ginkgolinter v0.22.0 h1:o9g7JN6efdBxAHhejvPkodEjWsOBze9zDnPePsvC/Qg= +github.com/nunnatsa/ginkgolinter v0.22.0/go.mod h1:zIFAk36fhcHQIiYOGXLbrGTXz7cvpufhRYem6ToCVnY= github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= @@ -316,8 +320,6 @@ github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.8.0 h1:DL4RestQqRLr8U4LygLw8g2DX6RN1eBJOpa2mzsrl1Q= -github.com/polyfloyd/go-errorlint v1.8.0/go.mod h1:G2W0Q5roxbLCt0ZQbdoxQxXktTjwNyDbEaj3n7jvl4s= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= @@ -445,8 +447,8 @@ go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo= go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE= go-simpler.org/sloglint v0.11.1 h1:xRbPepLT/MHPTCA6TS/wNfZrDzkGvCCqUv4Bdwc3H7s= go-simpler.org/sloglint v0.11.1/go.mod h1:2PowwiCOK8mjiF+0KGifVOT8ZsCNiFzvfyJeJOIt8MQ= -go.augendre.info/arangolint v0.3.1 h1:n2E6p8f+zfXSFLa2e2WqFPp4bfvcuRdd50y6cT65pSo= -go.augendre.info/arangolint v0.3.1/go.mod h1:6ZKzEzIZuBQwoSvlKT+qpUfIbBfFCE5gbAoTg0/117g= +go.augendre.info/arangolint v0.4.0 h1:xSCZjRoS93nXazBSg5d0OGCi9APPLNMmmLrC995tR50= +go.augendre.info/arangolint v0.4.0/go.mod h1:l+f/b4plABuFISuKnTGD4RioXiCCgghv2xqst/xOvAA= go.augendre.info/fatcontext v0.9.0 h1:Gt5jGD4Zcj8CDMVzjOJITlSb9cEch54hjRRlN3qDojE= go.augendre.info/fatcontext v0.9.0/go.mod h1:L94brOAT1OOUNue6ph/2HnwxoNlds9aXDF2FcUntbNw= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= @@ -530,8 +532,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= diff --git a/tools/vendor/github.com/polyfloyd/go-errorlint/LICENSE b/tools/vendor/codeberg.org/polyfloyd/go-errorlint/LICENSE similarity index 100% rename from tools/vendor/github.com/polyfloyd/go-errorlint/LICENSE rename to tools/vendor/codeberg.org/polyfloyd/go-errorlint/LICENSE diff --git a/tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/allowed.go b/tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/allowed.go similarity index 100% rename from tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/allowed.go rename to tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/allowed.go diff --git a/tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/analysis.go b/tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/analysis.go similarity index 100% rename from tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/analysis.go rename to tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/analysis.go diff --git a/tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/lint.go b/tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/lint.go similarity index 87% rename from tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/lint.go rename to tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/lint.go index 9ef6d585a..b7d3cbd5f 100644 --- a/tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/lint.go +++ b/tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/lint.go @@ -269,86 +269,88 @@ func LintErrorComparisons(info *TypesInfoExt) []analysis.Diagnostic { continue } - if switchComparesNonNil(switchStmt) { - diagnostic := analysis.Diagnostic{ - Message: "switch on an error will fail on wrapped errors. Use errors.Is to check for specific errors", - Pos: problematicCaseClause.Pos(), - } + if !switchComparesNonNil(switchStmt) { + continue + } - // Create a simpler version of the fix for switch statements - // We'll transform: switch err { case ErrX: ... } - // To: switch { case errors.Is(err, ErrX): ... } + diagnostic := analysis.Diagnostic{ + Message: "switch on an error will fail on wrapped errors. Use errors.Is to check for specific errors", + Pos: problematicCaseClause.Pos(), + } - // Create a new switch statement with an empty tag - newSwitchStmt := &ast.SwitchStmt{ - Init: switchStmt.Init, - Tag: nil, // Empty tag for the switch. - Body: &ast.BlockStmt{ - List: make([]ast.Stmt, len(switchStmt.Body.List)), - }, - } + // Create a simpler version of the fix for switch statements + // We'll transform: switch err { case ErrX: ... } + // To: switch { case errors.Is(err, ErrX): ... } - // Convert each case to use errors.Is. - switchTagExpr := switchStmt.Tag // The error variable being checked. - for i, stmt := range switchStmt.Body.List { - origCaseClause := stmt.(*ast.CaseClause) + // Create a new switch statement with an empty tag + newSwitchStmt := &ast.SwitchStmt{ + Init: switchStmt.Init, + Tag: nil, // Empty tag for the switch. + Body: &ast.BlockStmt{ + List: make([]ast.Stmt, len(switchStmt.Body.List)), + }, + } - // Create a new case clause. - newCaseClause := &ast.CaseClause{ - Body: origCaseClause.Body, - } + // Convert each case to use errors.Is. + switchTagExpr := switchStmt.Tag // The error variable being checked. + for i, stmt := range switchStmt.Body.List { + origCaseClause := stmt.(*ast.CaseClause) - // If this is a default case (no expressions), keep it as-is. - if len(origCaseClause.List) == 0 { - newCaseClause.List = nil // Default case. - newSwitchStmt.Body.List[i] = newCaseClause - continue - } + // Create a new case clause. + newCaseClause := &ast.CaseClause{ + Body: origCaseClause.Body, + } - newCaseClause.List = make([]ast.Expr, 0, len(origCaseClause.List)) - - // Convert each case expression. - for _, caseExpr := range origCaseClause.List { - if isNil(caseExpr) { - // Keep nil checks as is: case err == nil: - newCaseClause.List = append(newCaseClause.List, - &ast.BinaryExpr{ - X: switchTagExpr, - Op: token.EQL, - Y: caseExpr, - }) - continue - } - // Replace err == ErrX with errors.Is(err, ErrX). + // If this is a default case (no expressions), keep it as-is. + if len(origCaseClause.List) == 0 { + newCaseClause.List = nil // Default case. + newSwitchStmt.Body.List[i] = newCaseClause + continue + } + + newCaseClause.List = make([]ast.Expr, 0, len(origCaseClause.List)) + + // Convert each case expression. + for _, caseExpr := range origCaseClause.List { + if isNil(caseExpr) { + // Keep nil checks as is: case err == nil: newCaseClause.List = append(newCaseClause.List, - &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: ast.NewIdent("errors"), - Sel: ast.NewIdent("Is"), - }, - Args: []ast.Expr{switchTagExpr, caseExpr}, + &ast.BinaryExpr{ + X: switchTagExpr, + Op: token.EQL, + Y: caseExpr, }) + continue } - - newSwitchStmt.Body.List[i] = newCaseClause + // Replace err == ErrX with errors.Is(err, ErrX). + newCaseClause.List = append(newCaseClause.List, + &ast.CallExpr{ + Fun: &ast.SelectorExpr{ + X: ast.NewIdent("errors"), + Sel: ast.NewIdent("Is"), + }, + Args: []ast.Expr{switchTagExpr, caseExpr}, + }) } - // Print the modified AST to get the fix text. - var buf bytes.Buffer - printer.Fprint(&buf, token.NewFileSet(), newSwitchStmt) - fixText := buf.String() + newSwitchStmt.Body.List[i] = newCaseClause + } - diagnostic.SuggestedFixes = []analysis.SuggestedFix{{ - Message: "Convert to errors.Is() for error comparisons", - TextEdits: []analysis.TextEdit{{ - Pos: switchStmt.Pos(), - End: switchStmt.End(), - NewText: []byte(fixText), - }}, - }} + // Print the modified AST to get the fix text. + var buf bytes.Buffer + printer.Fprint(&buf, token.NewFileSet(), newSwitchStmt) + fixText := buf.String() - lints = append(lints, diagnostic) - } + diagnostic.SuggestedFixes = []analysis.SuggestedFix{{ + Message: "Convert to errors.Is() for error comparisons", + TextEdits: []analysis.TextEdit{{ + Pos: switchStmt.Pos(), + End: switchStmt.End(), + NewText: []byte(fixText), + }}, + }} + + lints = append(lints, diagnostic) } return lints @@ -646,6 +648,9 @@ func LintErrorTypeAssertions(fset *token.FileSet, info *TypesInfoExt) []analysis // Get the error variable being type-switched on errExpr := typeAssert.X + // a flag to know if we can fix the issue with a [analysis.SuggestedFix] + canFix := true + // Determine if this is a type switch with assignment (switch e := err.(type)) var assignIdent *ast.Ident var useShadowVar bool @@ -653,8 +658,18 @@ func LintErrorTypeAssertions(fset *token.FileSet, info *TypesInfoExt) []analysis // This is a type switch with assignment like: switch e := err.(type) if len(assignStmt.Lhs) == 1 { if id, ok := assignStmt.Lhs[0].(*ast.Ident); ok { - assignIdent = id - useShadowVar = true + if exprToString(errExpr) == id.Name { + // the switch with assignment is like switch err := err.(type) + // we cannot reuse err, otherwise it would lead to errors(err, &err) + canFix = false + + // TODO - suggest a fix with a new variable name instead? + // the issue is with the fact each branch should have a new variable name + } else { + // the variable names are different, we can reuse the assigned variable + assignIdent = id + useShadowVar = true + } } } } @@ -670,8 +685,8 @@ func LintErrorTypeAssertions(fset *token.FileSet, info *TypesInfoExt) []analysis for _, stmt := range typeSwitch.Body.List { caseClause := stmt.(*ast.CaseClause) for _, typeExpr := range caseClause.List { - // Skip default case (empty list) - if typeExpr != nil { + // Skip default case (empty list) and nil comparisons. + if typeExpr != nil && !isNil(typeExpr) { caseTypes = append(caseTypes, typeExpr) } } @@ -755,6 +770,16 @@ func LintErrorTypeAssertions(fset *token.FileSet, info *TypesInfoExt) []analysis newCaseClause.List = make([]ast.Expr, len(caseClause.List)) for j, typeExpr := range caseClause.List { + // Nil cases should become err == nil. + if isNil(typeExpr) { + newCaseClause.List[j] = &ast.BinaryExpr{ + X: errExpr, + Op: token.EQL, + Y: typeExpr, + } + continue + } + // Get the previously declared variable for this type. varName := typeToVar[typeExpr] @@ -802,20 +827,21 @@ func LintErrorTypeAssertions(fset *token.FileSet, info *TypesInfoExt) []analysis newSwitchStmt.Body.List[i] = newCaseClause } - // Print the resulting block to get the fix text. - var buf bytes.Buffer - printer.Fprint(&buf, token.NewFileSet(), blockStmt) - fixText := buf.String() - - diagnostic.SuggestedFixes = []analysis.SuggestedFix{{ - Message: "Convert type switch to use errors.As", - TextEdits: []analysis.TextEdit{{ - Pos: typeSwitch.Pos(), - End: typeSwitch.End(), - NewText: []byte(fixText), - }}, - }} + if canFix { + // Print the resulting block to get the fix text. + var buf bytes.Buffer + printer.Fprint(&buf, token.NewFileSet(), blockStmt) + fixText := buf.String() + diagnostic.SuggestedFixes = []analysis.SuggestedFix{{ + Message: "Convert type switch to use errors.As", + TextEdits: []analysis.TextEdit{{ + Pos: typeSwitch.Pos(), + End: typeSwitch.End(), + NewText: []byte(fixText), + }}, + }} + } lints = append(lints, diagnostic) } diff --git a/tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/options.go b/tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/options.go similarity index 56% rename from tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/options.go rename to tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/options.go index 4d7c742d8..64d4352f4 100644 --- a/tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/options.go +++ b/tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/options.go @@ -13,3 +13,15 @@ func WithAllowedWildcard(ap []AllowPair) Option { allowedWildcardAppend(ap) } } + +func WithComparison(enabled bool) Option { + return func() { + checkComparison = enabled + } +} + +func WithAsserts(enabled bool) Option { + return func() { + checkAsserts = enabled + } +} diff --git a/tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/printf.go b/tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/printf.go similarity index 100% rename from tools/vendor/github.com/polyfloyd/go-errorlint/errorlint/printf.go rename to tools/vendor/codeberg.org/polyfloyd/go-errorlint/errorlint/printf.go diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/README.md b/tools/vendor/github.com/MirrexOne/unqueryvet/README.md index 407f9d289..a5b2a3aed 100644 --- a/tools/vendor/github.com/MirrexOne/unqueryvet/README.md +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/README.md @@ -10,7 +10,14 @@ unqueryvet is a Go static analysis tool (linter) that detects `SELECT *` usage i - **Detects `SELECT *` in string literals** - Finds problematic queries in your Go code - **Constants and variables support** - Detects `SELECT *` in const and var declarations -- **SQL Builder support** - Works with popular SQL builders like Squirrel, GORM, etc. +- **String concatenation analysis** - Detects `SELECT *` in concatenated strings like `"SELECT * " + "FROM users"` +- **Format string analysis** - Detects `SELECT *` in `fmt.Sprintf`, `log.Printf`, and other format functions +- **Aliased wildcard detection** - Catches `SELECT t.*`, `SELECT alias.*` patterns +- **Subquery detection** - Finds `SELECT *` inside subqueries and nested queries +- **SQL Builder support** - Works with 8 popular SQL builders: Squirrel, GORM, SQLx, Ent, PGX, Bun, SQLBoiler, Jet +- **Auto-fix suggestions** - Provides suggested fixes for detected violations +- **File and function filtering** - Ignore specific files or functions using glob patterns +- **Configurable severity** - Set diagnostic severity to "error" or "warning" - **Highly configurable** - Extensive configuration options for different use cases - **Supports `//nolint:unqueryvet`** - Standard Go linting suppression - **golangci-lint integration** - Works seamlessly with golangci-lint @@ -33,6 +40,22 @@ Unqueryvet provides context-specific messages that explain WHY you should avoid query := "SELECT * FROM users" // avoid SELECT * - explicitly specify needed columns for better performance, maintainability and stability +// Aliased wildcards +query := "SELECT t.* FROM users t" +// avoid SELECT alias.* - explicitly specify columns like t.id, t.name for better maintainability + +// String concatenation +query := "SELECT * " + "FROM users" +// avoid SELECT * in concatenated string - explicitly specify needed columns + +// Format strings +query := fmt.Sprintf("SELECT * FROM %s", tableName) +// avoid SELECT * in format string - explicitly specify needed columns + +// Subqueries +query := "SELECT id FROM (SELECT * FROM users)" +// avoid SELECT * in subquery - explicitly specify needed columns + // SQL Builders query := squirrel.Select("*").From("users") // avoid SELECT * in SQL builder - explicitly specify columns to prevent unnecessary data transfer and schema change issues @@ -89,6 +112,20 @@ var QueryOrders = "SELECT * FROM orders" query := "SELECT * FROM users" rows, err := db.Query("SELECT * FROM orders WHERE status = ?", "active") +// Aliased wildcards +query := "SELECT t.* FROM users t" +query := "SELECT u.*, o.* FROM users u JOIN orders o ON u.id = o.user_id" + +// String concatenation +query := "SELECT * " + "FROM users " + "WHERE id = ?" + +// Format strings +query := fmt.Sprintf("SELECT * FROM %s WHERE id = %d", table, id) + +// Subqueries +query := "SELECT id FROM (SELECT * FROM users)" +query := "SELECT * FROM users WHERE id IN (SELECT * FROM orders)" + // SQL builders with SELECT * query := squirrel.Select("*").From("products") query := builder.Select().Columns("*").From("inventory") @@ -136,26 +173,94 @@ version: "2" linters: settings: - unqueryvet: - # Enable/disable SQL builder checking (default: true) - check-sql-builders: true - - # Default allowed patterns (automatically included): - # - COUNT(*), MAX(*), MIN(*) functions - # - information_schema, pg_catalog, sys schema queries - # You can add more patterns if needed: - # allowed-patterns: - # - "SELECT \\* FROM temp_.*" + unqueryvet: + # Enable/disable SQL builder checking (default: true) + check-sql-builders: true + + # Enable/disable aliased wildcard detection like SELECT t.* (default: true) + check-aliased-wildcard: true + + # Enable/disable string concatenation analysis (default: true) + check-string-concat: true + + # Enable/disable format string analysis like fmt.Sprintf (default: true) + check-format-strings: true + + # Enable/disable strings.Builder analysis (default: true) + check-string-builder: true + + # Enable/disable subquery analysis (default: true) + check-subqueries: true + + # Diagnostic severity: "error" or "warning" (default: "warning") + severity: warning + + # SQL builder libraries to check (all enabled by default) + sql-builders: + squirrel: true + gorm: true + sqlx: true + ent: true + pgx: true + bun: true + sqlboiler: true + jet: true + + # Patterns for files to ignore (glob patterns) + # ignored-files: + # - "*_test.go" + # - "testdata/**" + # - "mock_*.go" + + # Functions to ignore (regex patterns) + # ignored-functions: + # - "debug\\..*" + # - "test.*" + + # Default allowed patterns (automatically included): + # - COUNT(*), MAX(*), MIN(*) functions + # - information_schema, pg_catalog, sys schema queries + # You can add more patterns if needed: + # allowed-patterns: + # - "SELECT \\* FROM temp_.*" ``` ## Supported SQL Builders -Unqueryvet supports popular SQL builders out of the box: +Unqueryvet supports 8 popular SQL builders out of the box: + +| Library | Package | Detection | +|---------|---------|-----------| +| **Squirrel** | `github.com/Masterminds/squirrel` | `Select("*")`, `Columns("*")` | +| **GORM** | `gorm.io/gorm` | `Select("*")`, raw queries | +| **SQLx** | `github.com/jmoiron/sqlx` | `Select()`, raw queries | +| **Ent** | `entgo.io/ent` | Query builder patterns | +| **PGX** | `github.com/jackc/pgx` | `Query()`, `QueryRow()` | +| **Bun** | `github.com/uptrace/bun` | `NewSelect()`, raw queries | +| **SQLBoiler** | `github.com/volatiletech/sqlboiler` | Generated query methods | +| **Jet** | `github.com/go-jet/jet` | `SELECT()`, `STAR` | + +Each checker can be individually enabled/disabled via configuration. + +## Auto-Fix Suggestions + +Unqueryvet provides automatic fix suggestions for detected violations. When used with editors that support LSP or with `golangci-lint --fix`, you can quickly fix issues: + +```go +// Before (violation detected) +query := "SELECT * FROM users" + +// After auto-fix (with TODO placeholder) +query := "SELECT id, /* TODO: specify columns */ FROM users" + +// SQL builder before +squirrel.Select("*").From("users") + +// SQL builder after auto-fix +squirrel.Select("id", /* TODO: specify columns */).From("users") +``` -- **Squirrel** - `squirrel.Select("*")`, `Select().Columns("*")` -- **GORM** - Custom query methods -- **SQLBoiler** - Generated query methods -- **Custom builders** - Any builder using `Select()` patterns +The auto-fix adds `/* TODO: specify columns */` as a reminder to manually specify the columns you actually need. ## Integration Examples diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/analyzer.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/analyzer.go index ce9b9874c..023aa358c 100644 --- a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/analyzer.go +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/analyzer.go @@ -12,6 +12,7 @@ import ( "golang.org/x/tools/go/analysis/passes/inspect" "golang.org/x/tools/go/ast/inspector" + "github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders" "github.com/MirrexOne/unqueryvet/pkg/config" ) @@ -26,6 +27,15 @@ const ( defaultWarningMessage = "avoid SELECT * - explicitly specify needed columns for better performance, maintainability and stability" ) +// Precompiled regex patterns for performance +var ( + // aliasedWildcardPattern matches SELECT alias.* patterns like "SELECT t.*", "SELECT u.*, o.*" + aliasedWildcardPattern = regexp.MustCompile(`(?i)SELECT\s+(?:[A-Za-z_][A-Za-z0-9_]*\s*\.\s*\*\s*,?\s*)+`) + + // subquerySelectStarPattern matches SELECT * in subqueries like "(SELECT * FROM ...)" + subquerySelectStarPattern = regexp.MustCompile(`(?i)\(\s*SELECT\s+\*`) +) + // NewAnalyzer creates the Unqueryvet analyzer with enhanced logic for production use func NewAnalyzer() *analysis.Analyzer { return &analysis.Analyzer{ @@ -59,12 +69,34 @@ func RunWithConfig(pass *analysis.Pass, cfg *config.UnqueryvetSettings) (any, er cfg = &defaultSettings } + // Create filter context for efficient filtering + filter, err := NewFilterContext(cfg) + if err != nil { + // If filter creation fails, continue without filtering + filter = nil + } + + // Check if current file should be ignored + if filter != nil && len(pass.Files) > 0 { + fileName := pass.Fset.File(pass.Files[0].Pos()).Name() + if filter.IsIgnoredFile(fileName) { + return nil, nil + } + } + + // Create SQL builder registry for checking SQL builder patterns + var builderRegistry *sqlbuilders.Registry + if cfg.CheckSQLBuilders { + builderRegistry = sqlbuilders.NewRegistry(&cfg.SQLBuilders) + } + // Define AST node types we're interested in nodeFilter := []ast.Node{ (*ast.CallExpr)(nil), // Function/method calls (*ast.File)(nil), // Files (for SQL builder analysis) (*ast.AssignStmt)(nil), // Assignment statements for standalone literals (*ast.GenDecl)(nil), // General declarations (const, var, type) + (*ast.BinaryExpr)(nil), // Binary expressions for string concatenation } // Walk through all AST nodes and analyze them @@ -82,8 +114,46 @@ func RunWithConfig(pass *analysis.Pass, cfg *config.UnqueryvetSettings) (any, er // Check constant and variable declarations checkGenDecl(pass, node, cfg) case *ast.CallExpr: + // Check if function should be ignored + if filter != nil && filter.IsIgnoredFunction(node) { + return + } + + // Check format functions (fmt.Sprintf, etc.) + if cfg.CheckFormatStrings && CheckFormatFunction(pass, node, cfg) { + pass.Report(analysis.Diagnostic{ + Pos: node.Pos(), + Message: getDetailedWarningMessage("format_string"), + }) + return + } + + // Check SQL builder patterns + if builderRegistry != nil && builderRegistry.HasCheckers() { + violations := builderRegistry.Check(node) + for _, v := range violations { + pass.Report(analysis.Diagnostic{ + Pos: v.Pos, + End: v.End, + Message: v.Message, + }) + } + if len(violations) > 0 { + return + } + } + // Analyze function calls for SQL with SELECT * usage checkCallExpr(pass, node, cfg) + + case *ast.BinaryExpr: + // Check string concatenation for SELECT * + if cfg.CheckStringConcat && CheckConcatenation(pass, node, cfg) { + pass.Report(analysis.Diagnostic{ + Pos: node.Pos(), + Message: getDetailedWarningMessage("concat"), + }) + } } }) @@ -277,8 +347,9 @@ func isSelectStarQuery(query string, cfg *config.UnqueryvetSettings) bool { } } - // Check for SELECT * in query (case-insensitive) upperQuery := strings.ToUpper(query) + + // Check for SELECT * in query (case-insensitive) if strings.Contains(upperQuery, "SELECT *") { //nolint:unqueryvet // Ensure this is actually an SQL query by checking for SQL keywords sqlKeywords := []string{"FROM", "WHERE", "JOIN", "GROUP", "ORDER", "HAVING", "UNION", "LIMIT"} @@ -294,9 +365,30 @@ func isSelectStarQuery(query string, cfg *config.UnqueryvetSettings) bool { return true } } + + // Check for SELECT alias.* patterns (e.g., SELECT t.*, SELECT u.*, o.*) + if cfg.CheckAliasedWildcard && isSelectAliasStarQuery(query) { + return true + } + + // Check for SELECT * in subqueries (e.g., (SELECT * FROM ...)) + if cfg.CheckSubqueries && isSelectStarInSubquery(query) { + return true + } + return false } +// isSelectAliasStarQuery detects SELECT alias.* patterns like "SELECT t.*", "SELECT u.*, o.*" +func isSelectAliasStarQuery(query string) bool { + return aliasedWildcardPattern.MatchString(query) +} + +// isSelectStarInSubquery detects SELECT * in subqueries like "(SELECT * FROM ...)" +func isSelectStarInSubquery(query string) bool { + return subquerySelectStarPattern.MatchString(query) +} + // getWarningMessage returns informative warning message func getWarningMessage() string { return defaultWarningMessage @@ -311,6 +403,14 @@ func getDetailedWarningMessage(context string) string { return "avoid SELECT * in subquery - can cause performance issues and unexpected results when schema changes" case "empty_select": return "SQL builder Select() without columns defaults to SELECT * - add specific columns with .Columns() method" + case "aliased_wildcard": + return "avoid SELECT alias.* - explicitly specify columns like alias.id, alias.name for better maintainability" + case "subquery": + return "avoid SELECT * in subquery - specify columns explicitly to prevent issues when schema changes" + case "concat": + return "avoid SELECT * in concatenated query - explicitly specify needed columns" + case "format_string": + return "avoid SELECT * in format string - explicitly specify needed columns" default: return defaultWarningMessage } diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/concat.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/concat.go new file mode 100644 index 000000000..c4635ec84 --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/concat.go @@ -0,0 +1,100 @@ +// Package analyzer provides the SQL static analysis implementation for detecting SELECT * usage. +package analyzer + +import ( + "go/ast" + "go/token" + "strings" + + "golang.org/x/tools/go/analysis" + + "github.com/MirrexOne/unqueryvet/pkg/config" +) + +// StringConcatAnalyzer analyzes string concatenation expressions for SELECT * patterns. +// It traverses binary expressions to combine string parts and check for SELECT * usage. +type StringConcatAnalyzer struct { + pass *analysis.Pass + cfg *config.UnqueryvetSettings +} + +// NewStringConcatAnalyzer creates a new StringConcatAnalyzer. +func NewStringConcatAnalyzer(pass *analysis.Pass, cfg *config.UnqueryvetSettings) *StringConcatAnalyzer { + return &StringConcatAnalyzer{ + pass: pass, + cfg: cfg, + } +} + +// AnalyzeBinaryExpr analyzes a binary expression for string concatenation with SELECT *. +// Returns true if SELECT * was detected in the concatenated string. +func (sca *StringConcatAnalyzer) AnalyzeBinaryExpr(expr *ast.BinaryExpr) bool { + // Only analyze string concatenation (+ operator) + if expr.Op != token.ADD { + return false + } + + // Extract all string parts from the concatenation chain + parts := sca.extractStringParts(expr) + if len(parts) == 0 { + return false + } + + // Combine parts and check for SELECT * + combined := strings.Join(parts, "") + if combined == "" { + return false + } + + // Normalize and check for SELECT * + normalized := normalizeSQLQuery("\"" + combined + "\"") + return isSelectStarQuery(normalized, sca.cfg) +} + +// extractStringParts recursively extracts all string literal parts from a concatenation chain. +// For expressions like: "SELECT * " + "FROM " + tableName + " WHERE id = 1" +// It extracts: ["SELECT * ", "FROM ", " WHERE id = 1"] +func (sca *StringConcatAnalyzer) extractStringParts(expr ast.Expr) []string { + var parts []string + + switch e := expr.(type) { + case *ast.BasicLit: + // String literal + if e.Kind == token.STRING { + // Remove quotes from the string + value := strings.Trim(e.Value, "`\"") + parts = append(parts, value) + } + case *ast.BinaryExpr: + // Concatenation - recurse into both sides + if e.Op == token.ADD { + parts = append(parts, sca.extractStringParts(e.X)...) + parts = append(parts, sca.extractStringParts(e.Y)...) + } + case *ast.Ident: + // Variable reference - we can't know the value at compile time + // but we can check if it's a constant + if e.Obj != nil && e.Obj.Kind == ast.Con { + if valueSpec, ok := e.Obj.Decl.(*ast.ValueSpec); ok { + for _, value := range valueSpec.Values { + if lit, ok := value.(*ast.BasicLit); ok && lit.Kind == token.STRING { + strValue := strings.Trim(lit.Value, "`\"") + parts = append(parts, strValue) + } + } + } + } + case *ast.ParenExpr: + // Parenthesized expression - unwrap + parts = append(parts, sca.extractStringParts(e.X)...) + } + + return parts +} + +// CheckConcatenation is a convenience function to check a binary expression for SELECT *. +// It creates an analyzer and performs the check in one call. +func CheckConcatenation(pass *analysis.Pass, expr *ast.BinaryExpr, cfg *config.UnqueryvetSettings) bool { + analyzer := NewStringConcatAnalyzer(pass, cfg) + return analyzer.AnalyzeBinaryExpr(expr) +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/filter.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/filter.go new file mode 100644 index 000000000..5ad13b62f --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/filter.go @@ -0,0 +1,176 @@ +// Package analyzer provides the SQL static analysis implementation for detecting SELECT * usage. +package analyzer + +import ( + "go/ast" + "path/filepath" + "regexp" + "strings" + + "github.com/MirrexOne/unqueryvet/pkg/config" +) + +// FilterContext holds precompiled patterns for filtering files, functions, and queries. +// It provides efficient filtering by compiling regex patterns once during initialization. +type FilterContext struct { + ignoredFuncPatterns []*regexp.Regexp + ignoredFilePatterns []string + allowedPatterns []*regexp.Regexp +} + +// NewFilterContext creates a new FilterContext from settings. +// It precompiles all regex patterns for efficient filtering. +// Returns an error if any pattern is invalid. +func NewFilterContext(cfg *config.UnqueryvetSettings) (*FilterContext, error) { + fc := &FilterContext{ + ignoredFilePatterns: cfg.IgnoredFiles, + } + + // Compile ignored function patterns + for _, pattern := range cfg.IgnoredFunctions { + re, err := regexp.Compile(pattern) + if err != nil { + return nil, err + } + fc.ignoredFuncPatterns = append(fc.ignoredFuncPatterns, re) + } + + // Compile allowed query patterns + for _, pattern := range cfg.AllowedPatterns { + re, err := regexp.Compile(pattern) + if err != nil { + return nil, err + } + fc.allowedPatterns = append(fc.allowedPatterns, re) + } + + return fc, nil +} + +// IsIgnoredFunction checks if a function call should be ignored based on configured patterns. +// It extracts the full function name (package.function or receiver.method) and matches against patterns. +func (fc *FilterContext) IsIgnoredFunction(call *ast.CallExpr) bool { + if len(fc.ignoredFuncPatterns) == 0 { + return false + } + + funcName := extractFunctionName(call) + if funcName == "" { + return false + } + + for _, pattern := range fc.ignoredFuncPatterns { + if pattern.MatchString(funcName) { + return true + } + } + + return false +} + +// IsIgnoredFile checks if a file path matches any of the ignored file patterns. +// Supports glob patterns like "*_test.go", "testdata/**", "mock_*.go". +func (fc *FilterContext) IsIgnoredFile(filePath string) bool { + if len(fc.ignoredFilePatterns) == 0 { + return false + } + + // Normalize path separators for cross-platform support + normalizedPath := filepath.ToSlash(filePath) + baseName := filepath.Base(filePath) + + for _, pattern := range fc.ignoredFilePatterns { + // Try matching against full path + if matched, _ := filepath.Match(pattern, normalizedPath); matched { + return true + } + // Try matching against base name only + if matched, _ := filepath.Match(pattern, baseName); matched { + return true + } + // Handle ** patterns (recursive matching) + if strings.Contains(pattern, "**") { + if matchDoubleStarPattern(pattern, normalizedPath) { + return true + } + } + } + + return false +} + +// IsAllowedPattern checks if a query matches any of the allowed patterns. +// Returns true if the query should be allowed (not reported as a violation). +func (fc *FilterContext) IsAllowedPattern(query string) bool { + for _, pattern := range fc.allowedPatterns { + if pattern.MatchString(query) { + return true + } + } + return false +} + +// extractFunctionName extracts the full function name from a call expression. +// Returns formats like "pkg.Function", "receiver.Method", or just "Function". +func extractFunctionName(call *ast.CallExpr) string { + switch fun := call.Fun.(type) { + case *ast.SelectorExpr: + // Method call: obj.Method() or pkg.Function() + switch x := fun.X.(type) { + case *ast.Ident: + // pkg.Function() or receiver.Method() + return x.Name + "." + fun.Sel.Name + case *ast.SelectorExpr: + // Nested: pkg.subpkg.Function() + if ident, ok := x.X.(*ast.Ident); ok { + return ident.Name + "." + x.Sel.Name + "." + fun.Sel.Name + } + case *ast.CallExpr: + // Chained call: obj.Method1().Method2() + return fun.Sel.Name + } + return fun.Sel.Name + case *ast.Ident: + // Direct function call: Function() + return fun.Name + } + return "" +} + +// matchDoubleStarPattern handles glob patterns with ** (recursive matching). +// Example: "testdata/**" matches "testdata/foo/bar.go" +func matchDoubleStarPattern(pattern, path string) bool { + // Split pattern by ** + parts := strings.Split(pattern, "**") + if len(parts) != 2 { + return false + } + + prefix := strings.TrimSuffix(parts[0], "/") + suffix := strings.TrimPrefix(parts[1], "/") + + // Check if path starts with prefix + if prefix != "" && !strings.HasPrefix(path, prefix) { + return false + } + + // Check if path ends with suffix (if suffix exists) + if suffix != "" { + // Get the part after prefix + remainingPath := strings.TrimPrefix(path, prefix) + remainingPath = strings.TrimPrefix(remainingPath, "/") + + // Match suffix at the end or as a pattern + if matched, _ := filepath.Match(suffix, filepath.Base(path)); matched { + return true + } + if strings.HasSuffix(remainingPath, suffix) { + return true + } + } else { + // No suffix, just check prefix + return strings.HasPrefix(path, prefix) + } + + return false +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/fixes.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/fixes.go new file mode 100644 index 000000000..f059f063e --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/fixes.go @@ -0,0 +1,126 @@ +// Package analyzer provides the SQL static analysis implementation for detecting SELECT * usage. +package analyzer + +import ( + "go/token" + "regexp" + "strings" + + "golang.org/x/tools/go/analysis" +) + +// SuggestedFixGenerator generates auto-fix suggestions for SELECT * violations. +type SuggestedFixGenerator struct { + fset *token.FileSet +} + +// NewSuggestedFixGenerator creates a new SuggestedFixGenerator. +func NewSuggestedFixGenerator(fset *token.FileSet) *SuggestedFixGenerator { + return &SuggestedFixGenerator{ + fset: fset, + } +} + +// selectStarPattern matches SELECT * patterns for replacement +var selectStarFixPattern = regexp.MustCompile(`(?i)(SELECT\s+)\*(\s+FROM)`) + +// aliasedStarPattern matches SELECT alias.* patterns for replacement +var aliasedStarFixPattern = regexp.MustCompile(`(?i)(SELECT\s+)([A-Za-z_][A-Za-z0-9_]*)\s*\.\s*\*`) + +// GenerateFix creates a SuggestedFix for a SELECT * violation. +func (sfg *SuggestedFixGenerator) GenerateFix( + pos token.Pos, + end token.Pos, + originalText string, + violationType string, +) *analysis.SuggestedFix { + var newText string + var message string + + switch violationType { + case "select_star": + // Replace SELECT * with placeholder columns + newText = selectStarFixPattern.ReplaceAllString(originalText, "${1}id, /* TODO: specify columns */ ${2}") + message = "Replace SELECT * with explicit columns" + + case "aliased_wildcard": + // Replace SELECT t.* with placeholder + newText = aliasedStarFixPattern.ReplaceAllStringFunc(originalText, func(match string) string { + // Extract the alias + parts := aliasedStarFixPattern.FindStringSubmatch(match) + if len(parts) >= 3 { + alias := parts[2] + return parts[1] + alias + ".id, " + alias + "./* TODO: specify columns */" + } + return match + }) + message = "Replace SELECT alias.* with explicit columns" + + case "sql_builder_star": + // For SQL builder Select("*") -> Select("id", /* TODO */) + newText = strings.Replace(originalText, `"*"`, `"id", /* TODO: specify columns */`, 1) + message = "Replace \"*\" with explicit column names" + + case "empty_select": + // For empty Select() -> Select("id", /* TODO */) + newText = strings.Replace(originalText, "Select()", `Select("id", /* TODO: specify columns */)`, 1) + message = "Add column names to Select()" + + default: + // Generic replacement + newText = selectStarFixPattern.ReplaceAllString(originalText, "${1}id, /* TODO: specify columns */ ${2}") + message = "Replace SELECT * with explicit columns" + } + + // If no change was made, don't suggest a fix + if newText == originalText { + return nil + } + + return &analysis.SuggestedFix{ + Message: message, + TextEdits: []analysis.TextEdit{ + { + Pos: pos, + End: end, + NewText: []byte(newText), + }, + }, + } +} + +// GenerateColumnPlaceholder returns a placeholder string for explicit columns. +func (sfg *SuggestedFixGenerator) GenerateColumnPlaceholder() string { + return "id, /* TODO: specify columns */" +} + +// GenerateAliasedColumnPlaceholder returns a placeholder with table alias. +func (sfg *SuggestedFixGenerator) GenerateAliasedColumnPlaceholder(alias string) string { + return alias + ".id, " + alias + "./* TODO: specify columns */" +} + +// CreateDiagnosticWithFix creates a Diagnostic with an optional SuggestedFix. +func CreateDiagnosticWithFix( + pos token.Pos, + end token.Pos, + message string, + originalText string, + violationType string, + fset *token.FileSet, +) analysis.Diagnostic { + diagnostic := analysis.Diagnostic{ + Pos: pos, + End: end, + Message: message, + } + + // Generate fix if we have enough information + if originalText != "" && fset != nil { + generator := NewSuggestedFixGenerator(fset) + if fix := generator.GenerateFix(pos, end, originalText, violationType); fix != nil { + diagnostic.SuggestedFixes = []analysis.SuggestedFix{*fix} + } + } + + return diagnostic +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/format.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/format.go new file mode 100644 index 000000000..5fc827ed8 --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/format.go @@ -0,0 +1,217 @@ +// Package analyzer provides the SQL static analysis implementation for detecting SELECT * usage. +package analyzer + +import ( + "go/ast" + "go/token" + "strings" + + "golang.org/x/tools/go/analysis" + + "github.com/MirrexOne/unqueryvet/pkg/config" +) + +// formatFunctions maps package.function names to the index of the format string argument. +// Index -1 means the format string is the last argument (for variadic functions). +var formatFunctions = map[string]int{ + // fmt package + "fmt.Sprintf": 0, + "fmt.Printf": 0, + "fmt.Fprintf": 1, // first arg is io.Writer + "fmt.Errorf": 0, + "fmt.Fscanf": 1, + "fmt.Sscanf": 1, + "Sprintf": 0, // direct call after import + "Printf": 0, + "Errorf": 0, + + // log package + "log.Printf": 0, + "log.Fatalf": 0, + "log.Panicf": 0, + "log.Logf": 1, // first arg is log level + "Logger.Printf": 0, + "Logger.Fatalf": 0, + "Logger.Panicf": 0, + + // testing package + "testing.T.Logf": 0, + "testing.T.Errorf": 0, + "testing.T.Fatalf": 0, + "testing.T.Skipf": 0, + "testing.B.Logf": 0, + "testing.B.Errorf": 0, + "testing.B.Fatalf": 0, + "T.Logf": 0, + "T.Errorf": 0, + "T.Fatalf": 0, + "B.Logf": 0, + "B.Errorf": 0, + "B.Fatalf": 0, + + // errors package + "errors.Errorf": 0, + "errors.Wrapf": 1, // first arg is error + + // pkg/errors + "errors.WithMessagef": 1, + + // logrus + "logrus.Infof": 0, + "logrus.Warnf": 0, + "logrus.Errorf": 0, + "logrus.Debugf": 0, + "logrus.Fatalf": 0, + "logrus.Panicf": 0, + "logrus.Tracef": 0, + "logrus.Printf": 0, + "Entry.Infof": 0, + "Entry.Warnf": 0, + "Entry.Errorf": 0, + "Entry.Debugf": 0, + + // zap + "zap.S.Infof": 0, + "zap.S.Warnf": 0, + "zap.S.Errorf": 0, + "zap.S.Debugf": 0, + "zap.S.Fatalf": 0, + "zap.S.Panicf": 0, + "SugaredLogger.Infof": 0, + "SugaredLogger.Warnf": 0, + "SugaredLogger.Errorf": 0, + "SugaredLogger.Debugf": 0, +} + +// FormatStringAnalyzer analyzes format functions like fmt.Sprintf for SELECT * patterns. +type FormatStringAnalyzer struct { + pass *analysis.Pass + cfg *config.UnqueryvetSettings +} + +// NewFormatStringAnalyzer creates a new FormatStringAnalyzer. +func NewFormatStringAnalyzer(pass *analysis.Pass, cfg *config.UnqueryvetSettings) *FormatStringAnalyzer { + return &FormatStringAnalyzer{ + pass: pass, + cfg: cfg, + } +} + +// AnalyzeFormatCall analyzes a function call for format string patterns with SELECT *. +// Returns true if SELECT * was detected in the format string. +func (fsa *FormatStringAnalyzer) AnalyzeFormatCall(call *ast.CallExpr) bool { + // Get the function name + funcName := fsa.getFunctionName(call) + if funcName == "" { + return false + } + + // Check if this is a known format function + argIndex, ok := formatFunctions[funcName] + if !ok { + return false + } + + // Extract the format string + formatStr, ok := fsa.extractFormatString(call, argIndex) + if !ok { + return false + } + + // Check if the format string contains SELECT * + normalized := normalizeSQLQuery("\"" + formatStr + "\"") + return isSelectStarQuery(normalized, fsa.cfg) +} + +// getFunctionName extracts the function name from a call expression. +// Returns formats like "fmt.Sprintf", "log.Printf", or just "Sprintf". +func (fsa *FormatStringAnalyzer) getFunctionName(call *ast.CallExpr) string { + switch fun := call.Fun.(type) { + case *ast.SelectorExpr: + // Method call: pkg.Func() or obj.Method() + switch x := fun.X.(type) { + case *ast.Ident: + // pkg.Func() like fmt.Sprintf + return x.Name + "." + fun.Sel.Name + case *ast.SelectorExpr: + // Nested: pkg.subpkg.Func() or receiver.Type.Method() + if ident, ok := x.X.(*ast.Ident); ok { + return ident.Name + "." + x.Sel.Name + "." + fun.Sel.Name + } + // obj.Field.Method() + return x.Sel.Name + "." + fun.Sel.Name + case *ast.CallExpr: + // Chained: something().Method() + return fun.Sel.Name + } + return fun.Sel.Name + case *ast.Ident: + // Direct function call: Sprintf() (after import . "fmt") + return fun.Name + } + return "" +} + +// extractFormatString extracts the format string from a function call. +// argIndex specifies which argument contains the format string. +func (fsa *FormatStringAnalyzer) extractFormatString(call *ast.CallExpr, argIndex int) (string, bool) { + if argIndex < 0 || argIndex >= len(call.Args) { + return "", false + } + + arg := call.Args[argIndex] + + // Direct string literal + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + return strings.Trim(lit.Value, "`\""), true + } + + // Identifier (constant or variable) + if ident, ok := arg.(*ast.Ident); ok { + if ident.Obj != nil && ident.Obj.Kind == ast.Con { + // It's a constant - try to get its value + if valueSpec, ok := ident.Obj.Decl.(*ast.ValueSpec); ok { + for _, value := range valueSpec.Values { + if lit, ok := value.(*ast.BasicLit); ok && lit.Kind == token.STRING { + return strings.Trim(lit.Value, "`\""), true + } + } + } + } + } + + return "", false +} + +// CheckFormatFunction is a convenience function to check a call expression for SELECT *. +// It creates an analyzer and performs the check in one call. +func CheckFormatFunction(pass *analysis.Pass, call *ast.CallExpr, cfg *config.UnqueryvetSettings) bool { + analyzer := NewFormatStringAnalyzer(pass, cfg) + return analyzer.AnalyzeFormatCall(call) +} + +// IsFormatFunction checks if a call expression is a known format function. +func IsFormatFunction(call *ast.CallExpr) bool { + var funcName string + + switch fun := call.Fun.(type) { + case *ast.SelectorExpr: + switch x := fun.X.(type) { + case *ast.Ident: + funcName = x.Name + "." + fun.Sel.Name + case *ast.SelectorExpr: + if ident, ok := x.X.(*ast.Ident); ok { + funcName = ident.Name + "." + x.Sel.Name + "." + fun.Sel.Name + } else { + funcName = x.Sel.Name + "." + fun.Sel.Name + } + default: + funcName = fun.Sel.Name + } + case *ast.Ident: + funcName = fun.Name + } + + _, ok := formatFunctions[funcName] + return ok +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/bun.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/bun.go new file mode 100644 index 000000000..62bd63bde --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/bun.go @@ -0,0 +1,156 @@ +// Package sqlbuilders provides SQL builder library-specific checkers for SELECT * detection. +package sqlbuilders + +import ( + "go/ast" + "go/token" + "strings" +) + +// BunChecker checks github.com/uptrace/bun for SELECT * patterns. +type BunChecker struct{} + +// NewBunChecker creates a new BunChecker. +func NewBunChecker() *BunChecker { + return &BunChecker{} +} + +// Name returns the name of this checker. +func (c *BunChecker) Name() string { + return "bun" +} + +// IsApplicable checks if the call might be from bun. +func (c *BunChecker) IsApplicable(call *ast.CallExpr) bool { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return false + } + + // bun methods to check + bunMethods := []string{ + "NewSelect", "NewInsert", "NewUpdate", "NewDelete", + "Column", "ColumnExpr", "ExcludeColumn", + "Model", "Scan", "Exec", + "NewRaw", "Raw", + } + + for _, method := range bunMethods { + if sel.Sel.Name == method { + return true + } + } + + return false +} + +// CheckSelectStar checks for SELECT * in bun calls. +func (c *BunChecker) CheckSelectStar(call *ast.CallExpr) *SelectStarViolation { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return nil + } + + methodName := sel.Sel.Name + + // Check ColumnExpr("*") + if methodName == "ColumnExpr" || methodName == "Column" { + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + if value == "*" { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "bun " + methodName + "(\"*\") - explicitly specify columns", + Builder: "bun", + Context: "explicit_star", + } + } + } + } + } + + // Check NewRaw or Raw with SELECT * + if methodName == "NewRaw" || methodName == "Raw" { + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + upperValue := strings.ToUpper(value) + if strings.Contains(upperValue, "SELECT *") { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "bun Raw() with SELECT * - specify columns explicitly", + Builder: "bun", + Context: "raw_select_star", + } + } + } + } + } + + return nil +} + +// CheckChainedCalls checks method chains for SELECT * patterns. +func (c *BunChecker) CheckChainedCalls(call *ast.CallExpr) []*SelectStarViolation { + var violations []*SelectStarViolation + + // Track chain state + hasNewSelect := false + hasColumn := false + var selectCall *ast.CallExpr + + // Traverse the call chain + current := call + for current != nil { + sel, ok := current.Fun.(*ast.SelectorExpr) + if !ok { + break + } + + switch sel.Sel.Name { + case "NewSelect": + hasNewSelect = true + selectCall = current + case "Column", "ColumnExpr": + hasColumn = true + // Check for "*" argument + for _, arg := range current.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + if value == "*" { + violations = append(violations, &SelectStarViolation{ + Pos: current.Pos(), + End: current.End(), + Message: "bun Column(\"*\") in chain - specify columns explicitly", + Builder: "bun", + Context: "chained_star", + }) + } + } + } + case "Scan", "Exec": + // Terminal methods - check if we have NewSelect without Column + if hasNewSelect && !hasColumn && selectCall != nil { + violations = append(violations, &SelectStarViolation{ + Pos: selectCall.Pos(), + End: current.End(), + Message: "bun NewSelect() with Scan/Exec without Column() defaults to SELECT *", + Builder: "bun", + Context: "implicit_star", + }) + } + } + + // Move to the next call in the chain + if innerCall, ok := sel.X.(*ast.CallExpr); ok { + current = innerCall + } else { + break + } + } + + return violations +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/ent.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/ent.go new file mode 100644 index 000000000..f514bbb1c --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/ent.go @@ -0,0 +1,95 @@ +// Package sqlbuilders provides SQL builder library-specific checkers for SELECT * detection. +package sqlbuilders + +import ( + "go/ast" +) + +// EntChecker checks entgo.io/ent for SELECT * patterns. +type EntChecker struct{} + +// NewEntChecker creates a new EntChecker. +func NewEntChecker() *EntChecker { + return &EntChecker{} +} + +// Name returns the name of this checker. +func (c *EntChecker) Name() string { + return "ent" +} + +// IsApplicable checks if the call might be from ent. +func (c *EntChecker) IsApplicable(call *ast.CallExpr) bool { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return false + } + + // ent methods that could result in SELECT * + entMethods := []string{ + "Query", "All", "Only", "OnlyX", "First", "FirstX", + "QueryContext", "Select", + } + + for _, method := range entMethods { + if sel.Sel.Name == method { + return true + } + } + + return false +} + +// CheckSelectStar checks for SELECT * in ent calls. +func (c *EntChecker) CheckSelectStar(call *ast.CallExpr) *SelectStarViolation { + // ent typically doesn't have explicit SELECT * patterns + // The implicit SELECT * happens when Query().All() is called without Select() + return nil +} + +// CheckChainedCalls checks method chains for SELECT * patterns. +func (c *EntChecker) CheckChainedCalls(call *ast.CallExpr) []*SelectStarViolation { + var violations []*SelectStarViolation + + // Track chain state + hasQuery := false + hasSelect := false + var queryCall *ast.CallExpr + + // Traverse the call chain + current := call + for current != nil { + sel, ok := current.Fun.(*ast.SelectorExpr) + if !ok { + break + } + + switch sel.Sel.Name { + case "Query": + hasQuery = true + queryCall = current + case "Select": + hasSelect = true + case "All", "Only", "OnlyX", "First", "FirstX": + // Terminal methods - check if we have Query without Select + if hasQuery && !hasSelect && queryCall != nil { + violations = append(violations, &SelectStarViolation{ + Pos: queryCall.Pos(), + End: current.End(), + Message: "ent Query() with All/Only without Select() fetches all columns - use Select() to specify columns", + Builder: "ent", + Context: "implicit_star", + }) + } + } + + // Move to the next call in the chain + if innerCall, ok := sel.X.(*ast.CallExpr); ok { + current = innerCall + } else { + break + } + } + + return violations +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/gorm.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/gorm.go new file mode 100644 index 000000000..1946ad252 --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/gorm.go @@ -0,0 +1,201 @@ +// Package sqlbuilders provides SQL builder library-specific checkers for SELECT * detection. +package sqlbuilders + +import ( + "go/ast" + "go/token" + "strings" +) + +// GORMChecker checks gorm.io/gorm for SELECT * patterns. +type GORMChecker struct{} + +// NewGORMChecker creates a new GORMChecker. +func NewGORMChecker() *GORMChecker { + return &GORMChecker{} +} + +// Name returns the name of this checker. +func (c *GORMChecker) Name() string { + return "gorm" +} + +// IsApplicable checks if the call might be from GORM. +func (c *GORMChecker) IsApplicable(call *ast.CallExpr) bool { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return false + } + + // GORM methods to check + gormMethods := []string{ + "Select", "Find", "First", "Last", "Take", "Scan", + "Model", "Table", "Raw", "Exec", "Pluck", + "Preload", "Joins", "Where", "Or", "Not", + } + + for _, method := range gormMethods { + if sel.Sel.Name == method { + return true + } + } + + // Check for gorm package or DB type + if ident, ok := sel.X.(*ast.Ident); ok { + lowerName := strings.ToLower(ident.Name) + if lowerName == "gorm" || lowerName == "db" { + return true + } + } + + return false +} + +// CheckSelectStar checks for SELECT * in GORM calls. +func (c *GORMChecker) CheckSelectStar(call *ast.CallExpr) *SelectStarViolation { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return nil + } + + methodName := sel.Sel.Name + + // Check db.Select("*") + if methodName == "Select" { + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + if value == "*" { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "GORM Select(\"*\") - explicitly specify columns", + Builder: "gorm", + Context: "explicit_star", + } + } + // Check for SELECT * in raw SQL inside Select + upperValue := strings.ToUpper(value) + if strings.Contains(upperValue, "SELECT *") { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "GORM Select() contains SELECT * - specify columns explicitly", + Builder: "gorm", + Context: "raw_select_star", + } + } + } + } + } + + // Check db.Raw("SELECT * FROM ...") + if methodName == "Raw" { + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + upperValue := strings.ToUpper(value) + if strings.Contains(upperValue, "SELECT *") { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "GORM Raw() with SELECT * - specify columns explicitly", + Builder: "gorm", + Context: "raw_select_star", + } + } + } + } + } + + // Check db.Exec("SELECT * FROM ...") + if methodName == "Exec" { + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + upperValue := strings.ToUpper(value) + if strings.Contains(upperValue, "SELECT *") { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "GORM Exec() with SELECT * - specify columns explicitly", + Builder: "gorm", + Context: "raw_select_star", + } + } + } + } + } + + return nil +} + +// CheckChainedCalls checks method chains for SELECT * patterns. +func (c *GORMChecker) CheckChainedCalls(call *ast.CallExpr) []*SelectStarViolation { + var violations []*SelectStarViolation + + // Track chain state + hasModel := false + hasSelect := false + var modelCall *ast.CallExpr + + // Traverse the call chain + current := call + for current != nil { + sel, ok := current.Fun.(*ast.SelectorExpr) + if !ok { + break + } + + switch sel.Sel.Name { + case "Model", "Table": + hasModel = true + modelCall = current + case "Select": + hasSelect = true + // Check for "*" argument + for _, arg := range current.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + if value == "*" { + violations = append(violations, &SelectStarViolation{ + Pos: current.Pos(), + End: current.End(), + Message: "GORM Select(\"*\") in chain - specify columns explicitly", + Builder: "gorm", + Context: "chained_star", + }) + } + } + } + case "Find", "First", "Last", "Take", "Scan": + // Terminal methods - check if we have Model without Select + if hasModel && !hasSelect && modelCall != nil { + violations = append(violations, &SelectStarViolation{ + Pos: modelCall.Pos(), + End: current.End(), + Message: "GORM Model() with Find/First without Select() defaults to SELECT *", + Builder: "gorm", + Context: "implicit_star", + }) + } + case "Preload": + // Preload often uses SELECT * for eager loading - this is common but worth flagging + if len(current.Args) > 0 { + // Only flag if there's no second argument (no custom SQL) + if len(current.Args) == 1 { + // Could add a warning about Preload SELECT * + } + } + } + + // Move to the next call in the chain + if innerCall, ok := sel.X.(*ast.CallExpr); ok { + current = innerCall + } else { + break + } + } + + return violations +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/interface.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/interface.go new file mode 100644 index 000000000..ba7646fb4 --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/interface.go @@ -0,0 +1,107 @@ +// Package sqlbuilders provides SQL builder library-specific checkers for SELECT * detection. +package sqlbuilders + +import ( + "go/ast" + "go/token" + + "github.com/MirrexOne/unqueryvet/pkg/config" +) + +// SelectStarViolation represents a detected SELECT * usage in SQL builder code. +type SelectStarViolation struct { + // Pos is the position in source code where the violation was detected + Pos token.Pos + // End is the end position of the violation + End token.Pos + // Message is the human-readable description of the violation + Message string + // Builder is the name of the SQL builder library + Builder string + // Context provides additional context about the violation type + Context string +} + +// SQLBuilderChecker is the interface for SQL builder library-specific checkers. +// Each SQL builder library (GORM, sqlx, etc.) implements this interface. +type SQLBuilderChecker interface { + // Name returns the name of the SQL builder library + Name() string + + // IsApplicable checks if the call expression might be from this SQL builder + IsApplicable(call *ast.CallExpr) bool + + // CheckSelectStar checks a single call expression for SELECT * usage + CheckSelectStar(call *ast.CallExpr) *SelectStarViolation + + // CheckChainedCalls analyzes method chains for SELECT * patterns + CheckChainedCalls(call *ast.CallExpr) []*SelectStarViolation +} + +// Registry holds all registered SQL builder checkers and provides a unified interface. +type Registry struct { + checkers []SQLBuilderChecker +} + +// NewRegistry creates a new Registry with checkers based on the configuration. +func NewRegistry(cfg *config.SQLBuildersConfig) *Registry { + r := &Registry{ + checkers: make([]SQLBuilderChecker, 0), + } + + // Register enabled checkers + if cfg.Squirrel { + r.checkers = append(r.checkers, NewSquirrelChecker()) + } + if cfg.GORM { + r.checkers = append(r.checkers, NewGORMChecker()) + } + if cfg.SQLx { + r.checkers = append(r.checkers, NewSQLxChecker()) + } + if cfg.Ent { + r.checkers = append(r.checkers, NewEntChecker()) + } + if cfg.PGX { + r.checkers = append(r.checkers, NewPGXChecker()) + } + if cfg.Bun { + r.checkers = append(r.checkers, NewBunChecker()) + } + if cfg.SQLBoiler { + r.checkers = append(r.checkers, NewSQLBoilerChecker()) + } + if cfg.Jet { + r.checkers = append(r.checkers, NewJetChecker()) + } + + return r +} + +// Check analyzes a call expression against all registered checkers. +// Returns all violations found across all applicable checkers. +func (r *Registry) Check(call *ast.CallExpr) []*SelectStarViolation { + var violations []*SelectStarViolation + + for _, checker := range r.checkers { + if !checker.IsApplicable(call) { + continue + } + + // Check for direct SELECT * usage + if v := checker.CheckSelectStar(call); v != nil { + violations = append(violations, v) + } + + // Check for SELECT * in method chains + chainViolations := checker.CheckChainedCalls(call) + violations = append(violations, chainViolations...) + } + + return violations +} + +// HasCheckers returns true if at least one checker is registered. +func (r *Registry) HasCheckers() bool { + return len(r.checkers) > 0 +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/jet.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/jet.go new file mode 100644 index 000000000..ff5f123de --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/jet.go @@ -0,0 +1,192 @@ +// Package sqlbuilders provides SQL builder library-specific checkers for SELECT * detection. +package sqlbuilders + +import ( + "go/ast" + "go/token" + "strings" +) + +// JetChecker checks github.com/go-jet/jet for SELECT * patterns. +type JetChecker struct{} + +// NewJetChecker creates a new JetChecker. +func NewJetChecker() *JetChecker { + return &JetChecker{} +} + +// Name returns the name of this checker. +func (c *JetChecker) Name() string { + return "jet" +} + +// IsApplicable checks if the call might be from jet. +func (c *JetChecker) IsApplicable(call *ast.CallExpr) bool { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + // Check for direct SELECT call + if ident, ok := call.Fun.(*ast.Ident); ok { + return ident.Name == "SELECT" || ident.Name == "RawStatement" + } + return false + } + + // jet methods to check + jetMethods := []string{ + "SELECT", "FROM", "WHERE", + "AllColumns", "Star", + "RawStatement", "Raw", + } + + for _, method := range jetMethods { + if sel.Sel.Name == method { + return true + } + } + + return false +} + +// CheckSelectStar checks for SELECT * in jet calls. +func (c *JetChecker) CheckSelectStar(call *ast.CallExpr) *SelectStarViolation { + // Check for direct SELECT function call + if ident, ok := call.Fun.(*ast.Ident); ok { + if ident.Name == "SELECT" { + // Check arguments for AllColumns or STAR + for _, arg := range call.Args { + if c.isAllColumnsOrStar(arg) { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "Jet SELECT with AllColumns/STAR - specify columns explicitly", + Builder: "jet", + Context: "explicit_star", + } + } + } + } + + if ident.Name == "RawStatement" { + // Check for SELECT * in raw statement + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + upperValue := strings.ToUpper(value) + if strings.Contains(upperValue, "SELECT *") { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "Jet RawStatement with SELECT * - specify columns explicitly", + Builder: "jet", + Context: "raw_select_star", + } + } + } + } + } + } + + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return nil + } + + methodName := sel.Sel.Name + + // Check for table.AllColumns + if methodName == "AllColumns" { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "Jet AllColumns fetches all columns (SELECT *) - specify columns explicitly", + Builder: "jet", + Context: "all_columns", + } + } + + // Check for STAR constant usage + if methodName == "Star" { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "Jet Star() - avoid SELECT * and specify columns explicitly", + Builder: "jet", + Context: "explicit_star", + } + } + + // Check RawStatement + if methodName == "RawStatement" || methodName == "Raw" { + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + upperValue := strings.ToUpper(value) + if strings.Contains(upperValue, "SELECT *") { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "Jet Raw/RawStatement with SELECT * - specify columns explicitly", + Builder: "jet", + Context: "raw_select_star", + } + } + } + } + } + + return nil +} + +// CheckChainedCalls checks method chains for SELECT * patterns. +func (c *JetChecker) CheckChainedCalls(call *ast.CallExpr) []*SelectStarViolation { + var violations []*SelectStarViolation + + // Traverse the call chain looking for SELECT with AllColumns + current := call + for current != nil { + // Check arguments for AllColumns + for _, arg := range current.Args { + if c.isAllColumnsOrStar(arg) { + violations = append(violations, &SelectStarViolation{ + Pos: current.Pos(), + End: current.End(), + Message: "Jet SELECT chain contains AllColumns/STAR - specify columns explicitly", + Builder: "jet", + Context: "chained_star", + }) + } + } + + // Move to the next call in the chain + sel, ok := current.Fun.(*ast.SelectorExpr) + if !ok { + break + } + + if innerCall, ok := sel.X.(*ast.CallExpr); ok { + current = innerCall + } else { + break + } + } + + return violations +} + +// isAllColumnsOrStar checks if an expression represents AllColumns or STAR. +func (c *JetChecker) isAllColumnsOrStar(expr ast.Expr) bool { + switch e := expr.(type) { + case *ast.SelectorExpr: + // table.AllColumns or package.STAR + return e.Sel.Name == "AllColumns" || e.Sel.Name == "STAR" + case *ast.CallExpr: + // Check if it's a call to AllColumns() or Star() + if sel, ok := e.Fun.(*ast.SelectorExpr); ok { + return sel.Sel.Name == "AllColumns" || sel.Sel.Name == "Star" + } + case *ast.Ident: + // Direct STAR identifier + return e.Name == "STAR" || e.Name == "AllColumns" + } + return false +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/pgx.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/pgx.go new file mode 100644 index 000000000..9b44fc156 --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/pgx.go @@ -0,0 +1,94 @@ +// Package sqlbuilders provides SQL builder library-specific checkers for SELECT * detection. +package sqlbuilders + +import ( + "go/ast" + "go/token" + "strings" +) + +// PGXChecker checks github.com/jackc/pgx for SELECT * patterns. +type PGXChecker struct{} + +// NewPGXChecker creates a new PGXChecker. +func NewPGXChecker() *PGXChecker { + return &PGXChecker{} +} + +// Name returns the name of this checker. +func (c *PGXChecker) Name() string { + return "pgx" +} + +// IsApplicable checks if the call might be from pgx. +func (c *PGXChecker) IsApplicable(call *ast.CallExpr) bool { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return false + } + + // pgx methods that take SQL queries + pgxMethods := []string{ + "Query", "QueryRow", "QueryFunc", + "Exec", "SendBatch", + "Prepare", "CopyFrom", + } + + for _, method := range pgxMethods { + if sel.Sel.Name == method { + return true + } + } + + return false +} + +// CheckSelectStar checks for SELECT * in pgx calls. +func (c *PGXChecker) CheckSelectStar(call *ast.CallExpr) *SelectStarViolation { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return nil + } + + methodName := sel.Sel.Name + + // pgx methods where the SQL query is typically the second argument (after context) + queryArgIndex := 1 + switch methodName { + case "Query", "QueryRow", "Exec", "Prepare": + // conn.Query(ctx, sql, args...) + queryArgIndex = 1 + case "QueryFunc": + // conn.QueryFunc(ctx, sql, args, func...) + queryArgIndex = 1 + default: + return nil + } + + if queryArgIndex >= len(call.Args) { + return nil + } + + arg := call.Args[queryArgIndex] + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + upperValue := strings.ToUpper(value) + if strings.Contains(upperValue, "SELECT *") { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "pgx " + methodName + "() with SELECT * - specify columns explicitly", + Builder: "pgx", + Context: "raw_select_star", + } + } + } + + return nil +} + +// CheckChainedCalls checks method chains for SELECT * patterns. +func (c *PGXChecker) CheckChainedCalls(call *ast.CallExpr) []*SelectStarViolation { + // pgx doesn't have significant chaining patterns + return nil +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/sqlboiler.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/sqlboiler.go new file mode 100644 index 000000000..f4394c602 --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/sqlboiler.go @@ -0,0 +1,144 @@ +// Package sqlbuilders provides SQL builder library-specific checkers for SELECT * detection. +package sqlbuilders + +import ( + "go/ast" + "go/token" + "strings" +) + +// SQLBoilerChecker checks github.com/volatiletech/sqlboiler for SELECT * patterns. +type SQLBoilerChecker struct{} + +// NewSQLBoilerChecker creates a new SQLBoilerChecker. +func NewSQLBoilerChecker() *SQLBoilerChecker { + return &SQLBoilerChecker{} +} + +// Name returns the name of this checker. +func (c *SQLBoilerChecker) Name() string { + return "sqlboiler" +} + +// IsApplicable checks if the call might be from sqlboiler. +func (c *SQLBoilerChecker) IsApplicable(call *ast.CallExpr) bool { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return false + } + + // SQLBoiler methods + sqlboilerMethods := []string{ + "All", "One", "Count", "Exists", + "Select", "Load", "Reload", + } + + for _, method := range sqlboilerMethods { + if sel.Sel.Name == method { + return true + } + } + + // Check for qm (query mods) package + if ident, ok := sel.X.(*ast.Ident); ok { + if ident.Name == "qm" { + return true + } + } + + return false +} + +// CheckSelectStar checks for SELECT * in sqlboiler calls. +func (c *SQLBoilerChecker) CheckSelectStar(call *ast.CallExpr) *SelectStarViolation { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return nil + } + + methodName := sel.Sel.Name + + // Check qm.Select("*") + if methodName == "Select" { + // Check if caller is qm package + if ident, ok := sel.X.(*ast.Ident); ok && ident.Name == "qm" { + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + if value == "*" { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "SQLBoiler qm.Select(\"*\") - explicitly specify columns", + Builder: "sqlboiler", + Context: "explicit_star", + } + } + } + } + } + } + + return nil +} + +// CheckChainedCalls checks method chains for SELECT * patterns. +func (c *SQLBoilerChecker) CheckChainedCalls(call *ast.CallExpr) []*SelectStarViolation { + var violations []*SelectStarViolation + + // SQLBoiler uses query mods passed to model methods + // Example: models.Users(qm.Select("*")).All(ctx, db) + + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return violations + } + + // Check terminal methods + if sel.Sel.Name == "All" || sel.Sel.Name == "One" { + // Look for the model call that might have query mods + if innerCall, ok := sel.X.(*ast.CallExpr); ok { + // Check query mod arguments for Select("*") + hasSelect := false + for _, arg := range innerCall.Args { + // Check if this is a qm.Select call + if callExpr, ok := arg.(*ast.CallExpr); ok { + if innerSel, ok := callExpr.Fun.(*ast.SelectorExpr); ok { + if innerSel.Sel.Name == "Select" { + hasSelect = true + // Check for "*" + for _, selectArg := range callExpr.Args { + if lit, ok := selectArg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + if value == "*" { + violations = append(violations, &SelectStarViolation{ + Pos: callExpr.Pos(), + End: callExpr.End(), + Message: "SQLBoiler qm.Select(\"*\") - specify columns explicitly", + Builder: "sqlboiler", + Context: "explicit_star", + }) + } + } + } + } + } + } + } + + // If no Select query mod, it defaults to SELECT * + if !hasSelect && len(innerCall.Args) == 0 { + // Model().All() without query mods = SELECT * + violations = append(violations, &SelectStarViolation{ + Pos: innerCall.Pos(), + End: call.End(), + Message: "SQLBoiler model().All() without qm.Select() defaults to SELECT *", + Builder: "sqlboiler", + Context: "implicit_star", + }) + } + } + } + + return violations +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/sqlx.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/sqlx.go new file mode 100644 index 000000000..21e7ba804 --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/sqlx.go @@ -0,0 +1,100 @@ +// Package sqlbuilders provides SQL builder library-specific checkers for SELECT * detection. +package sqlbuilders + +import ( + "go/ast" + "go/token" + "strings" +) + +// SQLxChecker checks github.com/jmoiron/sqlx for SELECT * patterns. +type SQLxChecker struct{} + +// NewSQLxChecker creates a new SQLxChecker. +func NewSQLxChecker() *SQLxChecker { + return &SQLxChecker{} +} + +// Name returns the name of this checker. +func (c *SQLxChecker) Name() string { + return "sqlx" +} + +// IsApplicable checks if the call might be from sqlx. +func (c *SQLxChecker) IsApplicable(call *ast.CallExpr) bool { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return false + } + + // sqlx methods that take SQL queries + sqlxMethods := []string{ + "Select", "Get", "Queryx", "QueryRowx", + "NamedQuery", "NamedExec", "MustExec", + "Preparex", "PreparexContext", "PrepareNamed", + "Rebind", "In", + } + + for _, method := range sqlxMethods { + if sel.Sel.Name == method { + return true + } + } + + return false +} + +// CheckSelectStar checks for SELECT * in sqlx calls. +func (c *SQLxChecker) CheckSelectStar(call *ast.CallExpr) *SelectStarViolation { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return nil + } + + methodName := sel.Sel.Name + + // Methods where the SQL query is typically the first or second argument + queryArgIndex := 0 + switch methodName { + case "Select", "Get": + // db.Select(&dest, query, args...) + // db.Get(&dest, query, args...) + queryArgIndex = 1 + case "Queryx", "QueryRowx", "MustExec", "NamedExec": + // db.Queryx(query, args...) + queryArgIndex = 0 + case "NamedQuery": + // db.NamedQuery(query, arg) + queryArgIndex = 0 + default: + return nil + } + + if queryArgIndex >= len(call.Args) { + return nil + } + + arg := call.Args[queryArgIndex] + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + upperValue := strings.ToUpper(value) + if strings.Contains(upperValue, "SELECT *") { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "sqlx " + methodName + "() with SELECT * - specify columns explicitly", + Builder: "sqlx", + Context: "raw_select_star", + } + } + } + + return nil +} + +// CheckChainedCalls checks method chains for SELECT * patterns. +func (c *SQLxChecker) CheckChainedCalls(call *ast.CallExpr) []*SelectStarViolation { + // sqlx doesn't have significant chaining patterns like GORM + // Most queries are single method calls + return nil +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/squirrel.go b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/squirrel.go new file mode 100644 index 000000000..cb2e4ccaf --- /dev/null +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders/squirrel.go @@ -0,0 +1,190 @@ +// Package sqlbuilders provides SQL builder library-specific checkers for SELECT * detection. +package sqlbuilders + +import ( + "go/ast" + "go/token" + "strings" +) + +// SquirrelChecker checks github.com/Masterminds/squirrel for SELECT * patterns. +type SquirrelChecker struct{} + +// NewSquirrelChecker creates a new SquirrelChecker. +func NewSquirrelChecker() *SquirrelChecker { + return &SquirrelChecker{} +} + +// Name returns the name of this checker. +func (c *SquirrelChecker) Name() string { + return "squirrel" +} + +// IsApplicable checks if the call might be from Squirrel. +func (c *SquirrelChecker) IsApplicable(call *ast.CallExpr) bool { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return false + } + + // Squirrel methods to check + squirrelMethods := []string{ + "Select", "Columns", "Column", + "SelectBuilder", "InsertBuilder", "UpdateBuilder", "DeleteBuilder", + } + + for _, method := range squirrelMethods { + if sel.Sel.Name == method { + return true + } + } + + // Check for squirrel package prefix + if ident, ok := sel.X.(*ast.Ident); ok { + if ident.Name == "squirrel" || ident.Name == "sq" { + return true + } + } + + return false +} + +// CheckSelectStar checks for SELECT * in Squirrel calls. +func (c *SquirrelChecker) CheckSelectStar(call *ast.CallExpr) *SelectStarViolation { + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return nil + } + + methodName := sel.Sel.Name + + // Check squirrel.Select("*") or builder.Select("*") + if methodName == "Select" { + // Empty Select() means SELECT * + if len(call.Args) == 0 { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "Squirrel Select() without columns defaults to SELECT * - add specific columns", + Builder: "squirrel", + Context: "empty_select", + } + } + + // Check for "*" in arguments + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + if value == "*" || value == "" { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "Squirrel Select(\"*\") - explicitly specify columns", + Builder: "squirrel", + Context: "explicit_star", + } + } + } + } + } + + // Check Columns("*") or Column("*") + if methodName == "Columns" || methodName == "Column" { + for _, arg := range call.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + if value == "*" { + return &SelectStarViolation{ + Pos: call.Pos(), + End: call.End(), + Message: "Squirrel Columns(\"*\") - explicitly specify columns", + Builder: "squirrel", + Context: "explicit_star", + } + } + } + } + } + + return nil +} + +// CheckChainedCalls checks method chains for SELECT * patterns. +func (c *SquirrelChecker) CheckChainedCalls(call *ast.CallExpr) []*SelectStarViolation { + var violations []*SelectStarViolation + + // Traverse the call chain + current := call + hasSelect := false + hasColumns := false + var selectCall *ast.CallExpr + + for current != nil { + sel, ok := current.Fun.(*ast.SelectorExpr) + if !ok { + break + } + + switch sel.Sel.Name { + case "Select": + hasSelect = true + selectCall = current + // Check if Select has arguments + if len(current.Args) > 0 { + hasColumns = true + // Check for "*" argument + for _, arg := range current.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + if value == "*" { + violations = append(violations, &SelectStarViolation{ + Pos: current.Pos(), + End: current.End(), + Message: "Squirrel Select(\"*\") in chain - specify columns explicitly", + Builder: "squirrel", + Context: "chained_star", + }) + } + } + } + } + case "Columns", "Column": + hasColumns = true + // Check for "*" in Columns/Column + for _, arg := range current.Args { + if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { + value := strings.Trim(lit.Value, "`\"") + if value == "*" { + violations = append(violations, &SelectStarViolation{ + Pos: current.Pos(), + End: current.End(), + Message: "Squirrel Columns(\"*\") in chain - specify columns explicitly", + Builder: "squirrel", + Context: "chained_star", + }) + } + } + } + case "From", "Where", "Join", "LeftJoin", "RightJoin", "InnerJoin": + // Terminal methods - check if we have Select without columns + if hasSelect && !hasColumns && selectCall != nil && len(selectCall.Args) == 0 { + violations = append(violations, &SelectStarViolation{ + Pos: selectCall.Pos(), + End: selectCall.End(), + Message: "Squirrel Select() without columns in chain defaults to SELECT *", + Builder: "squirrel", + Context: "empty_select_chain", + }) + } + } + + // Move to the next call in the chain + if innerCall, ok := sel.X.(*ast.CallExpr); ok { + current = innerCall + } else { + break + } + } + + return violations +} diff --git a/tools/vendor/github.com/MirrexOne/unqueryvet/pkg/config/config.go b/tools/vendor/github.com/MirrexOne/unqueryvet/pkg/config/config.go index 034c324d1..1f201b526 100644 --- a/tools/vendor/github.com/MirrexOne/unqueryvet/pkg/config/config.go +++ b/tools/vendor/github.com/MirrexOne/unqueryvet/pkg/config/config.go @@ -9,12 +9,89 @@ type UnqueryvetSettings struct { // AllowedPatterns is a list of regex patterns that are allowed to use SELECT * // Example: ["SELECT \\* FROM temp_.*", "SELECT \\* FROM .*_backup"] AllowedPatterns []string `mapstructure:"allowed-patterns" json:"allowed-patterns" yaml:"allowed-patterns"` + + // IgnoredFunctions is a list of function name patterns to ignore + // Example: ["debug.Query", "test.*", "mock.*"] + IgnoredFunctions []string `mapstructure:"ignored-functions" json:"ignored-functions" yaml:"ignored-functions"` + + // IgnoredFiles is a list of glob patterns for files to ignore + // Example: ["*_test.go", "testdata/**", "mock_*.go"] + IgnoredFiles []string `mapstructure:"ignored-files" json:"ignored-files" yaml:"ignored-files"` + + // Severity defines the diagnostic severity: "error" or "warning" (default: "warning") + Severity string `mapstructure:"severity" json:"severity" yaml:"severity"` + + // CheckAliasedWildcard enables detection of SELECT alias.* patterns (e.g., SELECT t.* FROM users t) + CheckAliasedWildcard bool `mapstructure:"check-aliased-wildcard" json:"check-aliased-wildcard" yaml:"check-aliased-wildcard"` + + // CheckStringConcat enables detection of SELECT * in string concatenation (e.g., "SELECT * " + "FROM users") + CheckStringConcat bool `mapstructure:"check-string-concat" json:"check-string-concat" yaml:"check-string-concat"` + + // CheckFormatStrings enables detection of SELECT * in format functions (e.g., fmt.Sprintf) + CheckFormatStrings bool `mapstructure:"check-format-strings" json:"check-format-strings" yaml:"check-format-strings"` + + // CheckStringBuilder enables detection of SELECT * in strings.Builder usage + CheckStringBuilder bool `mapstructure:"check-string-builder" json:"check-string-builder" yaml:"check-string-builder"` + + // CheckSubqueries enables detection of SELECT * in subqueries (e.g., SELECT * FROM (SELECT * FROM ...)) + CheckSubqueries bool `mapstructure:"check-subqueries" json:"check-subqueries" yaml:"check-subqueries"` + + // SQLBuilders defines which SQL builder libraries to check + SQLBuilders SQLBuildersConfig `mapstructure:"sql-builders" json:"sql-builders" yaml:"sql-builders"` +} + +// SQLBuildersConfig defines which SQL builder libraries to analyze. +type SQLBuildersConfig struct { + // Squirrel enables checking github.com/Masterminds/squirrel + Squirrel bool `mapstructure:"squirrel" json:"squirrel" yaml:"squirrel"` + + // GORM enables checking gorm.io/gorm + GORM bool `mapstructure:"gorm" json:"gorm" yaml:"gorm"` + + // SQLx enables checking github.com/jmoiron/sqlx + SQLx bool `mapstructure:"sqlx" json:"sqlx" yaml:"sqlx"` + + // Ent enables checking entgo.io/ent + Ent bool `mapstructure:"ent" json:"ent" yaml:"ent"` + + // PGX enables checking github.com/jackc/pgx + PGX bool `mapstructure:"pgx" json:"pgx" yaml:"pgx"` + + // Bun enables checking github.com/uptrace/bun + Bun bool `mapstructure:"bun" json:"bun" yaml:"bun"` + + // SQLBoiler enables checking github.com/volatiletech/sqlboiler + SQLBoiler bool `mapstructure:"sqlboiler" json:"sqlboiler" yaml:"sqlboiler"` + + // Jet enables checking github.com/go-jet/jet + Jet bool `mapstructure:"jet" json:"jet" yaml:"jet"` +} + +// DefaultSQLBuildersConfig returns the default SQL builders configuration with all checkers enabled. +func DefaultSQLBuildersConfig() SQLBuildersConfig { + return SQLBuildersConfig{ + Squirrel: true, + GORM: true, + SQLx: true, + Ent: true, + PGX: true, + Bun: true, + SQLBoiler: true, + Jet: true, + } } -// DefaultSettings returns the default configuration for unqueryvet +// DefaultSettings returns the default configuration for unqueryvet. +// By default, all detection features are enabled for maximum coverage. func DefaultSettings() UnqueryvetSettings { return UnqueryvetSettings{ - CheckSQLBuilders: true, + CheckSQLBuilders: true, + CheckAliasedWildcard: true, + CheckStringConcat: true, + CheckFormatStrings: true, + CheckStringBuilder: true, + CheckSubqueries: true, + Severity: "warning", AllowedPatterns: []string{ `(?i)COUNT\(\s*\*\s*\)`, `(?i)MAX\(\s*\*\s*\)`, @@ -23,5 +100,8 @@ func DefaultSettings() UnqueryvetSettings { `(?i)SELECT \* FROM pg_catalog\..*`, `(?i)SELECT \* FROM sys\..*`, }, + IgnoredFunctions: []string{}, + IgnoredFiles: []string{}, + SQLBuilders: DefaultSQLBuildersConfig(), } } diff --git a/tools/vendor/github.com/alexkohler/prealloc/pkg/math.go b/tools/vendor/github.com/alexkohler/prealloc/pkg/math.go new file mode 100644 index 000000000..4335b0860 --- /dev/null +++ b/tools/vendor/github.com/alexkohler/prealloc/pkg/math.go @@ -0,0 +1,117 @@ +package pkg + +import ( + "go/ast" + "go/token" + "strconv" +) + +func addIntExpr(x, y ast.Expr) ast.Expr { + if x == nil || y == nil { + return nil + } + + xInt, xOK := intValue(x) + yInt, yOK := intValue(y) + + if xOK && yOK { + return intExpr(xInt + yInt) + } + if xOK { + if xInt == 0 { + return y + } + if xInt < 0 { + return &ast.BinaryExpr{X: y, Op: token.SUB, Y: intExpr(-xInt)} + } + } + if yOK { + if yInt == 0 { + return x + } + if yInt < 0 { + return &ast.BinaryExpr{X: x, Op: token.SUB, Y: intExpr(-yInt)} + } + } + if unary, ok := y.(*ast.UnaryExpr); ok && unary.Op == token.SUB { + return &ast.BinaryExpr{X: x, Op: token.SUB, Y: unary.X} + } + return &ast.BinaryExpr{X: x, Op: token.ADD, Y: y} +} + +func subIntExpr(x, y ast.Expr) ast.Expr { + if unary, ok := y.(*ast.UnaryExpr); ok && unary.Op == token.SUB { + y = unary.X + } else { + y = &ast.UnaryExpr{Op: token.SUB, X: y} + } + return addIntExpr(x, y) +} + +func mulIntExpr(x, y ast.Expr) ast.Expr { + if x == nil || y == nil { + return nil + } + + xInt, xOK := intValue(x) + yInt, yOK := intValue(y) + + if xOK && yOK { + return intExpr(xInt * yInt) + } + if xOK { + if xInt == 0 { + return intExpr(0) + } + if xInt == 1 { + return y + } + } + if yOK { + if yInt == 0 { + return intExpr(0) + } + if yInt == 1 { + return x + } + } + return &ast.BinaryExpr{X: x, Op: token.MUL, Y: y} +} + +func intExpr(n int) *ast.BasicLit { + return &ast.BasicLit{Kind: token.INT, Value: strconv.Itoa(n)} +} + +func intValue(expr ast.Expr) (int, bool) { + var negate bool + for { + switch e := expr.(type) { + case *ast.UnaryExpr: + if e.Op == token.SUB { + negate = !negate + expr = e.X + continue + } + case *ast.CallExpr: + if ident, ok := e.Fun.(*ast.Ident); ok && len(e.Args) == 1 { + switch ident.Name { + case "byte", "rune", "int", "int8", "int16", "int32", "int64", + "uint", "uint8", "uint16", "uint32", "uint64", "uintptr": + expr = e.Args[0] + continue + } + } + } + break + } + + if lit, ok := expr.(*ast.BasicLit); ok && lit.Kind == token.INT { + if i, err := strconv.Atoi(lit.Value); err == nil { + if negate { + return -i, true + } + return i, true + } + } + return 0, false +} diff --git a/tools/vendor/github.com/alexkohler/prealloc/pkg/prealloc.go b/tools/vendor/github.com/alexkohler/prealloc/pkg/prealloc.go index 72d8b95f7..8e9db4b21 100644 --- a/tools/vendor/github.com/alexkohler/prealloc/pkg/prealloc.go +++ b/tools/vendor/github.com/alexkohler/prealloc/pkg/prealloc.go @@ -1,15 +1,27 @@ package pkg import ( - "fmt" + "bytes" "go/ast" + "go/format" "go/token" + "strconv" + + "golang.org/x/tools/go/analysis" ) type sliceDeclaration struct { - name string - // sType string - genD *ast.GenDecl + name string + pos token.Pos + level int // Nesting level of this slice. Will be disqualified if appended at a deeper level. + lenExpr ast.Expr // Initial length of this slice. + exclude bool // Whether this slice has been disqualified due to an unsupported pattern. + hasReturn bool // Whether a return statement has been found after the first append. Any subsequent appends will disqualify this slice in simple mode. +} + +type sliceAppend struct { + index int // Index of the target slice. + countExpr ast.Expr // Number of items appended. } type returnsVisitor struct { @@ -18,250 +30,587 @@ type returnsVisitor struct { includeRangeLoops bool includeForLoops bool // visitor fields - sliceDeclarations []*sliceDeclaration - preallocHints []Hint - returnsInsideOfLoop bool - arrayTypes []string + sliceDeclarations []*sliceDeclaration + sliceAppends []*sliceAppend + preallocHints []analysis.Diagnostic + level int // Current nesting level. Loops do not increment the level. + hasReturn bool // Whether a return statement has been found. Slices appended before and after a return are disqualified in simple mode. + hasGoto bool // Whether a goto statement has been found. Goto disqualifies pending and subsequent slices in simple mode. + hasBranch bool // Whether a branch statement has been found. Loops with branch statements are unsupported in simple mode. } -func Check(files []*ast.File, simple, includeRangeLoops, includeForLoops bool) []Hint { - hints := []Hint{} +func Check(files []*ast.File, simple, includeRangeLoops, includeForLoops bool) []analysis.Diagnostic { + retVis := &returnsVisitor{ + simple: simple, + includeRangeLoops: includeRangeLoops, + includeForLoops: includeForLoops, + } for _, f := range files { - retVis := &returnsVisitor{ - simple: simple, - includeRangeLoops: includeRangeLoops, - includeForLoops: includeForLoops, - } ast.Walk(retVis, f) - // if simple is true, then we actually have to check if we had returns - // inside of our loop. Otherwise, we can just report all messages. - if !retVis.simple || !retVis.returnsInsideOfLoop { - hints = append(hints, retVis.preallocHints...) - } } - - return hints + return retVis.preallocHints } -func contains(slice []string, item string) bool { - for _, s := range slice { - if s == item { - return true +func (v *returnsVisitor) Visit(node ast.Node) ast.Visitor { + switch s := node.(type) { + case *ast.FuncDecl: + if s.Body == nil { + return nil } - } + v.level = 0 + v.hasReturn = false + v.hasGoto = false + ast.Walk(v, s.Body) + return nil + + case *ast.FuncLit: + if s.Body == nil { + return nil + } + wasReturn := v.hasReturn + wasGoto := v.hasGoto + v.hasReturn = false + ast.Walk(v, s.Body) + v.hasReturn = wasReturn + v.hasGoto = wasGoto + return nil + + case *ast.BlockStmt: + declIdx := len(v.sliceDeclarations) + appendIdx := len(v.sliceAppends) + v.level++ + for _, stmt := range s.List { + ast.Walk(v, stmt) + } + v.level-- - return false -} + buf := bytes.NewBuffer(nil) + for i := declIdx; i < len(v.sliceDeclarations); i++ { + sliceDecl := v.sliceDeclarations[i] + if sliceDecl.exclude || v.hasGoto { + continue + } -func (v *returnsVisitor) Visit(node ast.Node) ast.Visitor { + capExpr := sliceDecl.lenExpr + for j := appendIdx; j < len(v.sliceAppends); j++ { + if v.sliceAppends[j] != nil && v.sliceAppends[j].index == i { + capExpr = addIntExpr(capExpr, v.sliceAppends[j].countExpr) + } + } + if capExpr == sliceDecl.lenExpr { + // nothing appended + continue + } + if capVal, ok := intValue(capExpr); ok && capVal <= 0 { + continue + } - v.sliceDeclarations = nil - v.returnsInsideOfLoop = false + buf.Reset() + buf.WriteString("Consider preallocating ") + buf.WriteString(sliceDecl.name) + if capExpr != nil { + undo := buf.Len() + buf.WriteString(" with capacity ") + if format.Node(buf, token.NewFileSet(), capExpr) != nil { + buf.Truncate(undo) + } + } + v.preallocHints = append(v.preallocHints, analysis.Diagnostic{ + Pos: sliceDecl.pos, + Message: buf.String(), + }) + } - switch n := node.(type) { - case *ast.TypeSpec: - if _, ok := n.Type.(*ast.ArrayType); ok { - if n.Name != nil { - v.arrayTypes = append(v.arrayTypes, n.Name.Name) + // discard slices and associated appends that are falling out of scope + v.sliceDeclarations = v.sliceDeclarations[:declIdx] + for i := appendIdx; i < len(v.sliceAppends); i++ { + if v.sliceAppends[i] != nil { + if v.sliceAppends[i].index >= declIdx { + v.sliceAppends[i] = nil + } else { + appendIdx = i + 1 + } } } - case *ast.FuncDecl: - if n.Body != nil { - for _, stmt := range n.Body.List { - switch s := stmt.(type) { - // Find non pre-allocated slices - case *ast.DeclStmt: - genD, ok := s.Decl.(*ast.GenDecl) - if !ok { + v.sliceAppends = v.sliceAppends[:appendIdx] + return nil + + case *ast.ValueSpec: + _, isArrayType := inferExprType(s.Type).(*ast.ArrayType) + for i, name := range s.Names { + var lenExpr ast.Expr + if i >= len(s.Values) { + if !isArrayType { + continue + } + lenExpr = intExpr(0) + } else if lenExpr = isCreateArray(s.Values[i]); lenExpr == nil { + if id, ok := s.Values[i].(*ast.Ident); !ok || id.Name != "nil" { + continue + } + lenExpr = intExpr(0) + } + v.sliceDeclarations = append(v.sliceDeclarations, &sliceDeclaration{name: name.Name, pos: s.Pos(), level: v.level, lenExpr: lenExpr}) + } + + case *ast.AssignStmt: + if len(s.Lhs) != len(s.Rhs) { + return nil + } + for i, lhs := range s.Lhs { + ident, ok := lhs.(*ast.Ident) + if !ok { + continue + } + if lenExpr := isCreateArray(s.Rhs[i]); lenExpr != nil { + v.sliceDeclarations = append(v.sliceDeclarations, &sliceDeclaration{name: ident.Name, pos: s.Pos(), level: v.level, lenExpr: lenExpr}) + } else { + declIdx := -1 + for i := len(v.sliceDeclarations) - 1; i >= 0; i-- { + if v.sliceDeclarations[i].name == ident.Name { + declIdx = i + break + } + } + if declIdx < 0 { + continue + } + sliceDecl := v.sliceDeclarations[declIdx] + switch expr := s.Rhs[i].(type) { + case *ast.Ident: + // create a new slice declaration when reinitializing an existing slice to nil + if s.Tok == token.ASSIGN && expr.Name == "nil" { + v.sliceDeclarations = append(v.sliceDeclarations, &sliceDeclaration{name: ident.Name, pos: s.Pos(), level: v.level, lenExpr: intExpr(0)}) continue } - if genD.Tok == token.TYPE { - for _, spec := range genD.Specs { - tSpec, ok := spec.(*ast.TypeSpec) - if !ok { + case *ast.CallExpr: + if len(expr.Args) >= 2 && !sliceDecl.hasReturn && sliceDecl.level == v.level { + if funIdent, ok := expr.Fun.(*ast.Ident); ok && funIdent.Name == "append" { + if rhsIdent, ok := expr.Args[0].(*ast.Ident); ok && ident.Name == rhsIdent.Name { + v.sliceAppends = append(v.sliceAppends, &sliceAppend{index: declIdx, countExpr: appendCount(expr)}) continue } - - if _, ok := tSpec.Type.(*ast.ArrayType); ok { - if tSpec.Name != nil { - v.arrayTypes = append(v.arrayTypes, tSpec.Name.Name) - } - } - } - } else if genD.Tok == token.VAR { - for _, spec := range genD.Specs { - vSpec, ok := spec.(*ast.ValueSpec) - if !ok { - continue - } - var isArrType bool - switch val := vSpec.Type.(type) { - case *ast.ArrayType: - isArrType = true - case *ast.Ident: - isArrType = contains(v.arrayTypes, val.Name) - } - if isArrType { - if vSpec.Names != nil { - /*atID, ok := arrayType.Elt.(*ast.Ident) - if !ok { - continue - }*/ - - // We should handle multiple slices declared on same line e.g. var mySlice1, mySlice2 []uint32 - for _, vName := range vSpec.Names { - v.sliceDeclarations = append(v.sliceDeclarations, &sliceDeclaration{name: vName.Name /*sType: atID.Name,*/, genD: genD}) - } - } - } } } + } + sliceDecl.exclude = true + } + } - case *ast.RangeStmt: - if v.includeRangeLoops { - if len(v.sliceDeclarations) == 0 { - continue - } - // Check the value being ranged over and ensure it's not a channel (we cannot offer any recommendations on channel ranges). - rangeIdent, ok := s.X.(*ast.Ident) - if ok && rangeIdent.Obj != nil { - valueSpec, ok := rangeIdent.Obj.Decl.(*ast.ValueSpec) - if ok { - if _, rangeTargetIsChannel := valueSpec.Type.(*ast.ChanType); rangeTargetIsChannel { - continue - } - } - } - if s.Body != nil { - v.handleLoops(s.Body) - } - } + case *ast.RangeStmt: + return v.walkLoop(v.includeRangeLoops, s.Body, func() (ast.Expr, bool) { return rangeLoopCount(s) }) - case *ast.ForStmt: - if v.includeForLoops { - if len(v.sliceDeclarations) == 0 { - continue - } - if s.Body != nil { - v.handleLoops(s.Body) - } - } + case *ast.ForStmt: + return v.walkLoop(v.includeForLoops, s.Body, func() (ast.Expr, bool) { return forLoopCount(s) }) - default: - } + case *ast.SwitchStmt: + return v.walkSwitchSelect(s.Body) + + case *ast.TypeSwitchStmt: + return v.walkSwitchSelect(s.Body) + + case *ast.SelectStmt: + return v.walkSwitchSelect(s.Body) + + case *ast.ReturnStmt: + if !v.simple { + return nil + } + v.hasReturn = true + // flag all slices that have been appended at least once + for _, sliceApp := range v.sliceAppends { + if sliceApp != nil { + v.sliceDeclarations[sliceApp.index].hasReturn = true } } + + case *ast.BranchStmt: + if !v.simple { + return nil + } + if s.Label != nil { + v.hasGoto = true + } else { + v.hasBranch = true + } } + return v } -// handleLoops is a helper function to share the logic required for both *ast.RangeLoops and *ast.ForLoops -func (v *returnsVisitor) handleLoops(blockStmt *ast.BlockStmt) { +func (v *returnsVisitor) walkLoop(include bool, body *ast.BlockStmt, loopCount func() (ast.Expr, bool)) ast.Visitor { + if len(v.sliceDeclarations) == 0 { + return v + } + if body == nil { + return nil + } - for _, stmt := range blockStmt.List { - switch bodyStmt := stmt.(type) { - case *ast.AssignStmt: - asgnStmt := bodyStmt - for index, expr := range asgnStmt.Rhs { - if index >= len(asgnStmt.Lhs) { - continue + appendIdx := len(v.sliceAppends) + hadBranch := v.hasBranch + v.hasBranch = false + v.level-- + ast.Walk(v, body) + v.level++ + + exclude := !include || v.hasReturn || v.hasGoto || v.hasBranch + var loopCountExpr ast.Expr + if !exclude { + var ok bool + loopCountExpr, ok = loopCount() + exclude = !ok + } + if exclude { + // exclude all slices that were appended within this loop + for i := appendIdx; i < len(v.sliceAppends); i++ { + if v.sliceAppends[i] != nil { + v.sliceDeclarations[v.sliceAppends[i].index].exclude = true + } + } + } else { + for i := range v.sliceDeclarations { + prev := -1 + for j := len(v.sliceAppends) - 1; j >= appendIdx; j-- { + if v.sliceAppends[j] != nil && v.sliceAppends[j].index == i { + if prev >= 0 { + // consolidate appends to the same slice + v.sliceAppends[j].countExpr = addIntExpr(v.sliceAppends[j].countExpr, v.sliceAppends[prev].countExpr) + v.sliceAppends[prev] = nil + } else if loopCountExpr == nil { + // make appends indeterminate if the loop count is indeterminate + v.sliceAppends[j].countExpr = nil + } + prev = j } + } + if prev >= 0 { + v.sliceAppends[prev].countExpr = mulIntExpr(v.sliceAppends[prev].countExpr, loopCountExpr) + } + } + } + v.hasBranch = hadBranch + return nil +} - lhsIdent, ok := asgnStmt.Lhs[index].(*ast.Ident) - if !ok { - continue - } +func (v *returnsVisitor) walkSwitchSelect(body *ast.BlockStmt) ast.Visitor { + hadBranch := v.hasBranch + v.hasBranch = false + ast.Walk(v, body) + v.hasBranch = hadBranch + return nil +} - callExpr, ok := expr.(*ast.CallExpr) - if !ok { - continue - } +func isCreateArray(expr ast.Expr) ast.Expr { + switch e := expr.(type) { + case *ast.CompositeLit: + // []any{...} + if _, ok := inferExprType(e.Type).(*ast.ArrayType); ok { + return intExpr(len(e.Elts)) + } + case *ast.CallExpr: + switch len(e.Args) { + case 1: + // []any(nil) + arg, ok := e.Args[0].(*ast.Ident) + if !ok || arg.Name != "nil" { + return nil + } + if _, ok = inferExprType(e.Fun).(*ast.ArrayType); ok { + return intExpr(0) + } + case 2: + // make([]any, n) + ident, ok := e.Fun.(*ast.Ident) + if ok && ident.Name == "make" { + return e.Args[1] + } + } + } + return nil +} - rhsFuncIdent, ok := callExpr.Fun.(*ast.Ident) - if !ok { - continue - } +func sliceLength(expr ast.Expr) ast.Expr { + if call, ok := expr.(*ast.CallExpr); ok { + if len(call.Args) == 1 { + if _, ok := call.Fun.(*ast.ArrayType); ok { + expr = call.Args[0] + } + } else if len(call.Args) >= 2 { + if funIdent, ok := call.Fun.(*ast.Ident); ok && funIdent.Name == "append" { + return addIntExpr(sliceLength(call.Args[0]), appendCount(call)) + } + } + } - if rhsFuncIdent.Name != "append" { - continue + switch xType := inferExprType(expr).(type) { + case *ast.ArrayType: + if lit, ok := expr.(*ast.CompositeLit); ok { + return intExpr(len(lit.Elts)) + } + case *ast.Ident: + if xType.Name == "string" { + if lit, ok := expr.(*ast.BasicLit); ok && lit.Kind == token.STRING { + if str, err := strconv.Unquote(lit.Value); err == nil { + return intExpr(len(str)) } + } + } + default: + return nil + } - // e.g., `x = append(x)` - // Pointless, but pre-allocation will not help. - if len(callExpr.Args) < 2 { - continue - } + if hasCall(expr) { + return nil + } - rhsIdent, ok := callExpr.Args[0].(*ast.Ident) - if !ok { - continue - } + if slice, ok := expr.(*ast.SliceExpr); ok { + high := slice.High + if high == nil { + high = &ast.CallExpr{Fun: ast.NewIdent("len"), Args: []ast.Expr{slice.X}} + } + if slice.Low != nil { + return subIntExpr(high, slice.Low) + } + return high + } - // e.g., `x = append(y, a)` - // This is weird (and maybe a logic error), - // but we cannot recommend pre-allocation. - if lhsIdent.Name != rhsIdent.Name { - continue - } + return &ast.CallExpr{Fun: ast.NewIdent("len"), Args: []ast.Expr{expr}} +} - // e.g., `x = append(x, y...)` - // we should ignore this. Pre-allocating in this case - // is confusing, and is not possible in general. - if callExpr.Ellipsis.IsValid() { - continue - } +func rangeLoopCount(stmt *ast.RangeStmt) (ast.Expr, bool) { + x := stmt.X + if call, ok := x.(*ast.CallExpr); ok { + if len(call.Args) == 1 { + if _, ok := call.Fun.(*ast.ArrayType); ok { + x = call.Args[0] + } + } else if len(call.Args) >= 2 { + if funIdent, ok := call.Fun.(*ast.Ident); ok && funIdent.Name == "append" { + return addIntExpr(sliceLength(call.Args[0]), appendCount(call)), true + } + } + } - for _, sliceDecl := range v.sliceDeclarations { - if sliceDecl.name == lhsIdent.Name { - // This is a potential mark, we just need to make sure there are no returns/continues in the - // range loop. - // now we just need to grab whatever we're ranging over - /*sxIdent, ok := s.X.(*ast.Ident) - if !ok { - continue - }*/ - - v.preallocHints = append(v.preallocHints, Hint{ - Pos: sliceDecl.genD.Pos(), - DeclaredSliceName: sliceDecl.name, - }) - } - } + xType := inferExprType(x) + + switch xType := xType.(type) { + case *ast.ChanType, *ast.FuncType: + return nil, false + case *ast.ArrayType: + if lit, ok := stmt.X.(*ast.CompositeLit); ok { + if xType.Len != nil { + return xType.Len, true } - case *ast.IfStmt: - ifStmt := bodyStmt - if ifStmt.Body != nil { - for _, ifBodyStmt := range ifStmt.Body.List { - // TODO should probably handle embedded ifs here - switch /*ift :=*/ ifBodyStmt.(type) { - case *ast.BranchStmt, *ast.ReturnStmt: - v.returnsInsideOfLoop = true - default: - } + return intExpr(len(lit.Elts)), true + } + case *ast.MapType: + if lit, ok := x.(*ast.CompositeLit); ok { + return intExpr(len(lit.Elts)), true + } + case *ast.StarExpr: + if xType, ok := xType.X.(*ast.ArrayType); !ok || xType.Len == nil { + return nil, true + } else if unary, ok := x.(*ast.UnaryExpr); ok && unary.Op == token.AND { + if _, ok := unary.X.(*ast.CompositeLit); ok { + return xType.Len, true + } + } + case *ast.Ident: + if xType.Name == "string" { + if lit, ok := x.(*ast.BasicLit); ok && lit.Kind == token.STRING { + if str, err := strconv.Unquote(lit.Value); err == nil { + return intExpr(len(str)), true } } + } + default: + return nil, true + } + if hasCall(x) { + return nil, true + } + + if ident, ok := xType.(*ast.Ident); ok { + switch ident.Name { + case "byte", "rune", "int", "int8", "int16", "int32", "int64", + "uint", "uint8", "uint16", "uint32", "uint64", "uintptr": + return x, true + case "string": default: + return nil, true + } + } + if slice, ok := x.(*ast.SliceExpr); ok { + high := slice.High + if high == nil { + high = &ast.CallExpr{Fun: ast.NewIdent("len"), Args: []ast.Expr{slice.X}} } + if slice.Low != nil { + return subIntExpr(high, slice.Low), true + } + return high, true } + return &ast.CallExpr{Fun: ast.NewIdent("len"), Args: []ast.Expr{x}}, true } -// Hint stores the information about an occurrence of a slice that could be -// preallocated. -type Hint struct { - Pos token.Pos - DeclaredSliceName string +func appendCount(expr *ast.CallExpr) ast.Expr { + if expr.Ellipsis.IsValid() { + return sliceLength(expr.Args[1]) + } + return intExpr(len(expr.Args) - 1) } -func (h Hint) String() string { - return fmt.Sprintf("%v: Consider preallocating %v", h.Pos, h.DeclaredSliceName) +func forLoopCount(stmt *ast.ForStmt) (ast.Expr, bool) { + if stmt.Init == nil || stmt.Cond == nil || stmt.Post == nil { + return nil, false + } + + initStmt, ok := stmt.Init.(*ast.AssignStmt) + if !ok { + return nil, true + } + + postStmt, ok := stmt.Post.(*ast.IncDecStmt) + if !ok { + return nil, true + } + + postIdent, ok := postStmt.X.(*ast.Ident) + if !ok { + return nil, true + } + + index := -1 + for i := range initStmt.Lhs { + if ident, ok := initStmt.Lhs[i].(*ast.Ident); ok && ident.Name == postIdent.Name { + index = i + break + } + } + if index < 0 { + return nil, true + } + + lower := initStmt.Rhs[index] + if hasCall(lower) { + return nil, true + } + + upper, op := forLoopUpperBound(stmt.Cond, postIdent.Name) + + if postStmt.Tok == token.INC { + if op == token.GTR || op == token.GEQ { + return nil, false + } + } else { + if op == token.LSS || op == token.LEQ { + return nil, false + } + lower, upper = upper, lower + } + + countExpr := subIntExpr(upper, lower) + if op == token.LEQ || op == token.GEQ { + countExpr = addIntExpr(countExpr, intExpr(1)) + } + return countExpr, true } -func (h Hint) StringFromFS(f *token.FileSet) string { - file := f.File(h.Pos) - lineNumber := file.Position(h.Pos).Line +func forLoopUpperBound(expr ast.Expr, name string) (ast.Expr, token.Token) { + binExpr, ok := expr.(*ast.BinaryExpr) + if !ok { + return nil, 0 + } - return fmt.Sprintf("%v:%v Consider preallocating %v", file.Name(), lineNumber, h.DeclaredSliceName) + switch binExpr.Op { + case token.LAND, token.LOR: + if xExpr, xOp := forLoopUpperBound(binExpr.X, name); xExpr != nil { + if yExpr, yOp := forLoopUpperBound(binExpr.Y, name); yExpr != nil { + if xOp == yOp { + var funName string + if binExpr.Op == token.LAND { + funName = "min" + } else { + funName = "max" + } + if call, ok := xExpr.(*ast.CallExpr); ok { + if ident, ok := call.Fun.(*ast.Ident); ok && ident.Name == funName { + call.Args = append(call.Args, yExpr) + return xExpr, xOp + } + } + if call, ok := yExpr.(*ast.CallExpr); ok { + if ident, ok := call.Fun.(*ast.Ident); ok && ident.Name == funName { + call.Args = append(call.Args, xExpr) + return yExpr, yOp + } + } + return &ast.CallExpr{Fun: ast.NewIdent(funName), Args: []ast.Expr{xExpr, yExpr}}, xOp + } + } + } + + case token.LSS, token.GTR, token.LEQ, token.GEQ, token.NEQ: + if ident, ok := binExpr.X.(*ast.Ident); ok && ident.Name == name { + if hasCall(binExpr.Y) { + return nil, 0 + } + return binExpr.Y, binExpr.Op + } else if ident, ok := binExpr.Y.(*ast.Ident); ok && ident.Name == name { + if hasCall(binExpr.X) { + return nil, 0 + } + // reverse the inequality + op := binExpr.Op + switch op { + case token.LSS: + op = token.GTR + case token.GTR: + op = token.LSS + case token.LEQ: + op = token.GEQ + case token.GEQ: + op = token.LEQ + default: + } + return binExpr.X, op + } + + default: + } + + return nil, 0 +} + +func hasCall(expr ast.Expr) bool { + var found bool + ast.Inspect(expr, func(n ast.Node) bool { + if call, ok := n.(*ast.CallExpr); ok { + switch fun := call.Fun.(type) { + case *ast.ArrayType, *ast.MapType: + // allow array/map type convertion + return true + case *ast.Ident: + switch fun.Name { + case "bool", "error", "string", "any", + "byte", "rune", "int", "int8", "int16", "int32", "int64", + "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", + "float32", "float64", "complex64", "complex128": + // allow built-in type conversions + if len(call.Args) == 1 { + return true + } + case "len", "cap", "real", "imag", "min", "max", "complex": + // allow cheap pure built-in functions + return true + } + } + found = true + } + return !found + }) + return found } diff --git a/tools/vendor/github.com/alexkohler/prealloc/pkg/types.go b/tools/vendor/github.com/alexkohler/prealloc/pkg/types.go new file mode 100644 index 000000000..6d0561590 --- /dev/null +++ b/tools/vendor/github.com/alexkohler/prealloc/pkg/types.go @@ -0,0 +1,376 @@ +package pkg + +import ( + "go/ast" + "go/token" +) + +func inferExprType(expr ast.Expr) ast.Expr { + switch e := expr.(type) { + case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType: + return e + case *ast.ParenExpr: + return inferExprType(e.X) + case *ast.SliceExpr: + return inferExprType(e.X) + case *ast.TypeAssertExpr: + return inferExprType(e.Type) + case *ast.CompositeLit: + return inferExprType(e.Type) + case *ast.Ellipsis: + return &ast.ArrayType{Elt: e.Elt} + case *ast.FuncLit: + return &ast.FuncType{Results: e.Type.Results} + case *ast.BasicLit: + return inferBasicType(e) + case *ast.BinaryExpr: + return inferBinaryType(e) + case *ast.StarExpr: + return inferStarType(e) + case *ast.UnaryExpr: + return inferUnaryType(e) + case *ast.CallExpr: + return inferCallType(e) + case *ast.IndexExpr: + return inferIndexType(e) + case *ast.IndexListExpr: + return inferIndexListType(e) + case *ast.SelectorExpr: + return inferSelectorType(e) + case *ast.Ident: + return inferIdentType(e) + default: + return nil + } +} + +func inferBasicType(basic *ast.BasicLit) ast.Expr { + switch basic.Kind { + case token.INT: + return ast.NewIdent("int") + case token.FLOAT: + return ast.NewIdent("float64") + case token.IMAG: + return ast.NewIdent("imag") + case token.CHAR: + return ast.NewIdent("char") + case token.STRING: + return ast.NewIdent("string") + default: + return nil + } +} + +func inferBinaryType(binary *ast.BinaryExpr) ast.Expr { + switch binary.Op { + case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ: + return ast.NewIdent("bool") + default: + if x := inferExprType(binary.X); x != nil { + return x + } + return inferExprType(binary.Y) + } +} + +func inferStarType(star *ast.StarExpr) ast.Expr { + switch x := inferExprType(star.X).(type) { + case nil: + return nil + case *ast.StarExpr: + return inferExprType(x.X) + default: + return &ast.StarExpr{X: x} + } +} + +func inferUnaryType(unary *ast.UnaryExpr) ast.Expr { + if x := inferExprType(unary.X); x != nil { + switch unary.Op { + case token.AND: + return &ast.StarExpr{X: x} + case token.ARROW: + if ct, ok := x.(*ast.ChanType); ok { + return inferExprType(ct.Value) + } + return x + default: + return x + } + } + return nil +} + +func inferCallType(call *ast.CallExpr) ast.Expr { + if id, ok := call.Fun.(*ast.Ident); ok && id.Obj == nil { + switch id.Name { + case "len", "cap", "copy": + return ast.NewIdent("int") + case "real", "imag": + return ast.NewIdent("float64") + case "complex": + return ast.NewIdent("complex64") + case "recover": + return ast.NewIdent("any") + case "make", "min", "max": + if len(call.Args) > 0 { + return inferExprType(call.Args[0]) + } + case "new": + if len(call.Args) > 0 { + if arg := inferExprType(call.Args[0]); arg != nil { + return &ast.StarExpr{X: arg} + } + } + case "append": + if len(call.Args) > 0 { + if arg := inferExprType(call.Args[0]); arg != nil { + return arg + } + return &ast.ArrayType{} + } + } + } + + fun := inferExprType(call.Fun) + if ft, ok := fun.(*ast.FuncType); ok && len(ft.Results.List) > 0 { + return inferExprType(ft.Results.List[0].Type) + } + return fun +} + +func inferIndexType(index *ast.IndexExpr) ast.Expr { + if selector, ok := index.X.(*ast.SelectorExpr); ok && selector.Sel != nil && selector.Sel.Name == "Seq" { + if ident, ok := selector.X.(*ast.Ident); ok && ident.Name == "iter" { + return &ast.FuncType{ + Params: &ast.FieldList{List: []*ast.Field{{ + Names: []*ast.Ident{{Name: "yield"}}, + Type: &ast.FuncType{ + Params: &ast.FieldList{List: []*ast.Field{{Type: ast.NewIdent("V")}}}, + Results: &ast.FieldList{List: []*ast.Field{{Type: ast.NewIdent("bool")}}}, + }, + }}}, + } + } + } + + switch x := inferExprType(index.X).(type) { + case *ast.ArrayType: + return inferExprType(x.Elt) + case *ast.MapType: + return inferExprType(x.Value) + default: + return x + } +} + +func inferIndexListType(index *ast.IndexListExpr) ast.Expr { + if selector, ok := index.X.(*ast.SelectorExpr); ok && selector.Sel != nil && selector.Sel.Name == "Seq2" { + if ident, ok := selector.X.(*ast.Ident); ok && ident.Name == "iter" { + return &ast.FuncType{ + Params: &ast.FieldList{List: []*ast.Field{{ + Names: []*ast.Ident{{Name: "yield"}}, + Type: &ast.FuncType{ + Params: &ast.FieldList{List: []*ast.Field{ + {Type: ast.NewIdent("K")}, + {Type: ast.NewIdent("V")}, + }}, + Results: &ast.FieldList{List: []*ast.Field{{Type: ast.NewIdent("bool")}}}, + }, + }}}, + } + } + } + + x := inferExprType(index.X) + if at, ok := x.(*ast.ArrayType); ok { + return inferExprType(at.Elt) + } + return x +} + +func inferSelectorType(sel *ast.SelectorExpr) ast.Expr { + x := inferExprType(sel.X) + if se, ok := x.(*ast.StarExpr); ok { + x = se.X + } + switch x := x.(type) { + case *ast.StructType: + for _, field := range x.Fields.List { + for _, name := range field.Names { + if name.Name == sel.Sel.Name { + return inferExprType(field.Type) + } + } + } + case *ast.InterfaceType: + for _, method := range x.Methods.List { + for _, name := range method.Names { + if name.Name == sel.Sel.Name { + return inferExprType(method.Type) + } + } + } + } + return nil +} + +func inferIdentType(ident *ast.Ident) ast.Expr { + if ident.Obj == nil { + switch ident.Name { + case "bool", "byte", "comparable", "error", "rune", "string", "any", + "int", "int8", "int16", "int32", "int64", + "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", + "float32", "float64", "complex64", "complex128": + return ident + case "nil": + return ast.NewIdent("any") + case "true", "false": + return ast.NewIdent("bool") + case "iota": + return ast.NewIdent("int") + } + } else { + switch decl := ident.Obj.Decl.(type) { + case *ast.Field: + return inferExprType(decl.Type) + case *ast.FuncDecl: + return inferExprType(decl.Type) + case *ast.TypeSpec: + // abort when recursive pointer type detected + t := decl.Type + for { + if star, ok := t.(*ast.StarExpr); ok { + t = star.X + } else if t == ident { + return nil + } else { + break + } + } + return inferExprType(decl.Type) + case *ast.ValueSpec: + return inferValueType(decl, ident.Name) + case *ast.AssignStmt: + return inferAssignType(decl, ident.Name) + } + } + return nil +} + +func inferValueType(value *ast.ValueSpec, name string) ast.Expr { + if value.Type != nil { + return inferExprType(value.Type) + } + + index := -1 + for i := range value.Names { + if value.Names[i].Name == name { + index = i + } + } + if index < 0 { + return nil + } + + if len(value.Names) == len(value.Values) { + return inferExprType(value.Values[index]) + } + + return inferAssignMultiType(value.Values[0], index) +} + +func inferAssignType(assign *ast.AssignStmt, name string) ast.Expr { + index := -1 + for i := range assign.Lhs { + if id, ok := assign.Lhs[i].(*ast.Ident); ok && id.Name == name { + index = i + } + } + if index < 0 { + return nil + } + + if len(assign.Rhs) == 1 { + if ue, ok := assign.Rhs[0].(*ast.UnaryExpr); ok && ue.Op == token.RANGE { + switch rhs := inferExprType(assign.Rhs[0]).(type) { + case *ast.ArrayType: + switch index { + case 0: + return ast.NewIdent("int") + case 1: + return inferExprType(rhs.Elt) + } + case *ast.MapType: + switch index { + case 0: + return inferExprType(rhs.Key) + case 1: + return inferExprType(rhs.Value) + } + case *ast.Ident: + if rhs.Name == "string" { + switch index { + case 0: + return ast.NewIdent("int") + case 1: + return ast.NewIdent("rune") + } + } + case *ast.ChanType: + if index == 0 { + return inferExprType(rhs.Value) + } + } + } + } + + if len(assign.Lhs) == len(assign.Rhs) { + return inferExprType(assign.Rhs[index]) + } + + return inferAssignMultiType(assign.Rhs[0], index) +} + +func inferAssignMultiType(rhs ast.Expr, index int) ast.Expr { + switch rhs := rhs.(type) { + case *ast.TypeAssertExpr: + switch index { + case 0: + return inferExprType(rhs.Type) + case 1: + return ast.NewIdent("bool") + } + case *ast.CallExpr: + if fun, ok := inferExprType(rhs.Fun).(*ast.FuncType); ok { + for _, res := range fun.Results.List { + for range res.Names { + if index == 0 { + return inferExprType(res.Type) + } + index-- + } + } + } + case *ast.IndexExpr: + if mt, ok := inferExprType(rhs.X).(*ast.MapType); ok { + switch index { + case 0: + return inferExprType(mt.Value) + case 1: + return ast.NewIdent("bool") + } + } + case *ast.UnaryExpr: + if ct, ok := inferExprType(rhs.X).(*ast.ChanType); ok { + switch index { + case 0: + return inferExprType(ct.Value) + case 1: + return ast.NewIdent("bool") + } + } + } + + return nil +} diff --git a/tools/vendor/github.com/go-critic/go-critic/checkers/embedded_rules.go b/tools/vendor/github.com/go-critic/go-critic/checkers/embedded_rules.go index ad507425e..0d448399e 100644 --- a/tools/vendor/github.com/go-critic/go-critic/checkers/embedded_rules.go +++ b/tools/vendor/github.com/go-critic/go-critic/checkers/embedded_rules.go @@ -6,6 +6,7 @@ import ( "go/build" "go/token" "os" + "sync" "github.com/go-critic/go-critic/checkers/rulesdata" "github.com/go-critic/go-critic/linter" @@ -15,6 +16,42 @@ import ( //go:generate go run ./rules/precompile.go -rules ./rules/rules.go -o ./rulesdata/rulesdata.go +// cachedEngine holds a pre-initialized ruleguard engine for a specific rule group. +// The engine is created once and reused for all checker instances. +type cachedEngine struct { + engine *ruleguard.Engine + once sync.Once + err error + + // Configuration needed to create the engine + fset *token.FileSet + buildContext *build.Context + groupName string + debug bool +} + +func (ce *cachedEngine) get() (*ruleguard.Engine, error) { + ce.once.Do(func() { + parseContext := &ruleguard.LoadContext{ + Fset: ce.fset, + GroupFilter: func(gr *ruleguard.GoRuleGroup) bool { + return gr.Name == ce.groupName + }, + DebugImports: ce.debug, + DebugPrint: func(s string) { + fmt.Println("debug:", s) + }, + } + engine := ruleguard.NewEngine() + engine.BuildContext = ce.buildContext + ce.err = engine.LoadFromIR(parseContext, "rules/rules.go", rulesdata.PrecompiledRules) + if ce.err == nil { + ce.engine = engine + } + }) + return ce.engine, ce.err +} + func InitEmbeddedRules() error { filename := "rules/rules.go" @@ -49,8 +86,8 @@ func InitEmbeddedRules() error { groups = rootEngine.LoadedGroups() } - // For every rules group we create a new checker and a separate engine. - // That dedicated ruleguard engine will contain rules only from one group. + // For every rules group we create a cached engine holder. + // The engine will be created lazily on first use and then reused. for i := range groups { g := groups[i] info := &linter.CheckerInfo{ @@ -63,20 +100,17 @@ func InitEmbeddedRules() error { EmbeddedRuleguard: true, } + + // Create a cached engine for this rule group + cache := &cachedEngine{ + fset: fset, + buildContext: buildContext, + groupName: g.Name, + debug: ruleguardDebug, + } + collection.AddChecker(info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - parseContext := &ruleguard.LoadContext{ - Fset: fset, - GroupFilter: func(gr *ruleguard.GoRuleGroup) bool { - return gr.Name == g.Name - }, - DebugImports: ruleguardDebug, - DebugPrint: func(s string) { - fmt.Println("debug:", s) - }, - } - engine := ruleguard.NewEngine() - engine.BuildContext = buildContext - err := engine.LoadFromIR(parseContext, filename, rulesdata.PrecompiledRules) + engine, err := cache.get() if err != nil { return nil, err } diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/max_len/max_len.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/max_len/max_len.go index 1d647c49e..fba28c96e 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/max_len/max_len.go +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/max_len/max_len.go @@ -4,11 +4,14 @@ package max_len import ( "fmt" gdc "go/doc/comment" + "regexp" + "slices" "strings" "unicode/utf8" "github.com/godoc-lint/godoc-lint/pkg/model" "github.com/godoc-lint/godoc-lint/pkg/util" + "golang.org/x/tools/go/analysis" ) const maxLenRule = model.MaxLenRule @@ -32,6 +35,7 @@ func (r *MaxLenChecker) GetCoveredRules() model.RuleSet { func (r *MaxLenChecker) Apply(actx *model.AnalysisContext) error { includeTests := actx.Config.GetRuleOptions().MaxLenIncludeTests maxLen := int(actx.Config.GetRuleOptions().MaxLenLength) + ignoreRegexps := actx.Config.GetRuleOptions().MaxLenIgnorePatterns docs := make(map[*model.CommentGroup]struct{}, 10*len(actx.InspectorResult.Files)) @@ -52,12 +56,12 @@ func (r *MaxLenChecker) Apply(actx *model.AnalysisContext) error { } for doc := range docs { - checkMaxLen(actx, doc, maxLen) + checkMaxLen(actx, doc, maxLen, ignoreRegexps) } return nil } -func checkMaxLen(actx *model.AnalysisContext, doc *model.CommentGroup, maxLen int) { +func checkMaxLen(actx *model.AnalysisContext, doc *model.CommentGroup, maxLen int, ignoreRegexps []*regexp.Regexp) { if doc.DisabledRules.All || doc.DisabledRules.Rules.Has(maxLenRule) { return } @@ -81,14 +85,68 @@ func checkMaxLen(actx *model.AnalysisContext, doc *model.CommentGroup, maxLen in text := string((&gdc.Printer{}).Comment(strippedCodeAndLinks)) linesIter := strings.SplitSeq(removeCarriageReturn(text), "\n") + // This is a clone of the original comment list since we need to remove + // elements from it, if needed. The main purpose of this is to don't miss + // duplicate long lines. + cgl := slices.Clone(doc.CG.List) + for l := range linesIter { lineLen := utf8.RuneCountInString(l) if lineLen <= maxLen { continue } - actx.Pass.ReportRangef(&doc.CG, "godoc line is too long (%d > %d)", lineLen, maxLen) - break + if shouldIgnoreLine(l, ignoreRegexps) { + continue + } + + // Here we try to find the accurate position of the line within the + // original comment group. Historically, we would use the entire godoc + // block range to report the issue (See #55). + // + // However, the following approach does not work with /*..*/ comment + // blocks, since for them individual lines are not separately available, + // i.e. all lines would be in a single ast.Comment instance and + // therefore the ast.Comment.Pos will always point to the starting /* + // token. + + foundAt := -1 + for i, c := range cgl { + // As of [ast.Comment] docs, c.Text does not include carriage + // returns (\r) that may have been present in the source. This is + // good, since we have already stripped them from the lines. + // + // If the comment is a //-style one, c.Text starts with "// ". Since + // we're only interested in //-style cases, it's enough to check for + // that prefix. + if c.Text == "// "+l { + foundAt = i + break + } + } + + var rng analysis.Range + if foundAt != -1 { + rng = cgl[foundAt] + // Remove the found comment line from the list so that we don't miss + // duplicate long lines, or even reporting the same line number more + // than once while leaving the other(s). + cgl = slices.Delete(cgl, foundAt, foundAt+1) + } else { + // Fallback to reporting the entire godoc block. + rng = &doc.CG + } + + actx.Pass.ReportRangef(rng, "godoc line is too long (%d > %d)", lineLen, maxLen) + } +} + +func shouldIgnoreLine(line string, ignoreRegexps []*regexp.Regexp) bool { + for _, re := range ignoreRegexps { + if re.MatchString(line) { + return true + } } + return false } func removeCarriageReturn(s string) string { diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/registry.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/registry.go index 8452fa02c..657fa8bc4 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/registry.go +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/registry.go @@ -8,6 +8,7 @@ import ( "github.com/godoc-lint/godoc-lint/pkg/check/pkg_doc" "github.com/godoc-lint/godoc-lint/pkg/check/require_doc" "github.com/godoc-lint/godoc-lint/pkg/check/start_with_name" + "github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink" "github.com/godoc-lint/godoc-lint/pkg/model" ) @@ -37,6 +38,7 @@ func NewPopulatedRegistry() *Registry { start_with_name.NewStartWithNameChecker(), no_unused_link.NewNoUnusedLinkChecker(), deprecated.NewDeprecatedChecker(), + stdlib_doclink.NewStdlibDoclinkChecker(), ) } diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/require_doc/require_doc.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/require_doc/require_doc.go index afa16bd78..de2436b7b 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/require_doc/require_doc.go +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/require_doc/require_doc.go @@ -40,6 +40,12 @@ func (r *RequireDocChecker) Apply(actx *model.AnalysisContext) error { for _, ir := range util.AnalysisApplicableFiles(actx, includeTests, model.RuleSet{}.Add(requireDocRule)) { for _, decl := range ir.SymbolDecl { isExported := ast.IsExported(decl.Name) + if decl.IsMethod && decl.MethodRecvBaseTypeName != "" { + // A method is considered exported (in terms of godoc visibility) + // only if both the method name and the base type name are exported. + isExported = isExported && ast.IsExported(decl.MethodRecvBaseTypeName) + } + if isExported && !requirePublic || !isExported && !requirePrivate { continue } diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/start_with_name/start_with_name.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/start_with_name/start_with_name.go index f8c905aab..13c933dad 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/start_with_name/start_with_name.go +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/start_with_name/start_with_name.go @@ -41,6 +41,12 @@ func (r *StartWithNameChecker) Apply(actx *model.AnalysisContext) error { for _, ir := range util.AnalysisApplicableFiles(actx, includeTests, model.RuleSet{}.Add(startWithNameRule)) { for _, decl := range ir.SymbolDecl { isExported := ast.IsExported(decl.Name) + if decl.IsMethod && decl.MethodRecvBaseTypeName != "" { + // A method is considered exported (in terms of godoc visibility) + // only if both the method name and the base type name are exported. + isExported = isExported && ast.IsExported(decl.MethodRecvBaseTypeName) + } + if !isExported && !includePrivate { continue } diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/data.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/data.go new file mode 100644 index 000000000..92fb8b1bc --- /dev/null +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/data.go @@ -0,0 +1,27 @@ +package stdlib_doclink + +import ( + "bytes" + _ "embed" + "encoding/json" + "sync" + + "github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/internal" +) + +//go:embed stdlib.json +var stdlibRaw []byte + +var stdlib = sync.OnceValue(func() internal.Stdlib { + v, _ := parseStdlib() + return v +}) + +func parseStdlib() (internal.Stdlib, error) { + result := internal.Stdlib{} + if err := json.NewDecoder(bytes.NewReader(stdlibRaw)).Decode(&result); err != nil { + // This never happens + return internal.Stdlib{}, err + } + return result, nil +} diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/internal/type.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/internal/type.go new file mode 100644 index 000000000..4197695e1 --- /dev/null +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/internal/type.go @@ -0,0 +1,30 @@ +// Package internal contains internal types for stdlib_doclink checker. +package internal + +import ( + _ "embed" +) + +// SymbolKind represents the kind of a symbol in the standard library. +type SymbolKind string + +// Kinds of symbols. +const ( + SymbolKindNA SymbolKind = "" + SymbolKindConst SymbolKind = "c" + SymbolKindVar SymbolKind = "v" + SymbolKindFunc SymbolKind = "f" + SymbolKindMethod SymbolKind = "m" + SymbolKindType SymbolKind = "t" +) + +// StdlibPackage represents a standard library package with its path, name, and +// symbols. +type StdlibPackage struct { + Path string `json:"path"` + Name string `json:"name"` + Symbols map[string]SymbolKind `json:"symbols"` +} + +// Stdlib represents a collection of standard library packages. +type Stdlib map[string]*StdlibPackage diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/stdlib.json b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/stdlib.json new file mode 100644 index 000000000..840ba17b5 --- /dev/null +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/stdlib.json @@ -0,0 +1 @@ +{"archive/tar":{"path":"archive/tar","name":"tar","symbols":{"ErrFieldTooLong":"v","ErrHeader":"v","ErrInsecurePath":"v","ErrWriteAfterClose":"v","ErrWriteTooLong":"v","FileInfoHeader":"f","FileInfoNames":"t","Format":"t","Format.String":"m","FormatGNU":"c","FormatPAX":"c","FormatUSTAR":"c","FormatUnknown":"c","Header":"t","Header.FileInfo":"m","NewReader":"f","NewWriter":"f","Reader":"t","Reader.Next":"m","Reader.Read":"m","TypeBlock":"c","TypeChar":"c","TypeCont":"c","TypeDir":"c","TypeFifo":"c","TypeGNULongLink":"c","TypeGNULongName":"c","TypeGNUSparse":"c","TypeLink":"c","TypeReg":"c","TypeRegA":"c","TypeSymlink":"c","TypeXGlobalHeader":"c","TypeXHeader":"c","Writer":"t","Writer.AddFS":"m","Writer.Close":"m","Writer.Flush":"m","Writer.Write":"m","Writer.WriteHeader":"m"}},"archive/zip":{"path":"archive/zip","name":"zip","symbols":{"Compressor":"t","Decompressor":"t","Deflate":"c","ErrAlgorithm":"v","ErrChecksum":"v","ErrFormat":"v","ErrInsecurePath":"v","File":"t","File.DataOffset":"m","File.Open":"m","File.OpenRaw":"m","FileHeader":"t","FileHeader.FileInfo":"m","FileHeader.ModTime":"m","FileHeader.Mode":"m","FileHeader.SetModTime":"m","FileHeader.SetMode":"m","FileInfoHeader":"f","NewReader":"f","NewWriter":"f","OpenReader":"f","ReadCloser":"t","ReadCloser.Close":"m","Reader":"t","Reader.Open":"m","Reader.RegisterDecompressor":"m","RegisterCompressor":"f","RegisterDecompressor":"f","Store":"c","Writer":"t","Writer.AddFS":"m","Writer.Close":"m","Writer.Copy":"m","Writer.Create":"m","Writer.CreateHeader":"m","Writer.CreateRaw":"m","Writer.Flush":"m","Writer.RegisterCompressor":"m","Writer.SetComment":"m","Writer.SetOffset":"m"}},"bufio":{"path":"bufio","name":"bufio","symbols":{"ErrAdvanceTooFar":"v","ErrBadReadCount":"v","ErrBufferFull":"v","ErrFinalToken":"v","ErrInvalidUnreadByte":"v","ErrInvalidUnreadRune":"v","ErrNegativeAdvance":"v","ErrNegativeCount":"v","ErrTooLong":"v","MaxScanTokenSize":"c","NewReadWriter":"f","NewReader":"f","NewReaderSize":"f","NewScanner":"f","NewWriter":"f","NewWriterSize":"f","ReadWriter":"t","Reader":"t","Reader.Buffered":"m","Reader.Discard":"m","Reader.Peek":"m","Reader.Read":"m","Reader.ReadByte":"m","Reader.ReadBytes":"m","Reader.ReadLine":"m","Reader.ReadRune":"m","Reader.ReadSlice":"m","Reader.ReadString":"m","Reader.Reset":"m","Reader.Size":"m","Reader.UnreadByte":"m","Reader.UnreadRune":"m","Reader.WriteTo":"m","ScanBytes":"f","ScanLines":"f","ScanRunes":"f","ScanWords":"f","Scanner":"t","Scanner.Buffer":"m","Scanner.Bytes":"m","Scanner.Err":"m","Scanner.Scan":"m","Scanner.Split":"m","Scanner.Text":"m","SplitFunc":"t","Writer":"t","Writer.Available":"m","Writer.AvailableBuffer":"m","Writer.Buffered":"m","Writer.Flush":"m","Writer.ReadFrom":"m","Writer.Reset":"m","Writer.Size":"m","Writer.Write":"m","Writer.WriteByte":"m","Writer.WriteRune":"m","Writer.WriteString":"m"}},"builtin":{"path":"builtin","name":"builtin","symbols":{"ComplexType":"t","FloatType":"t","IntegerType":"t","Type":"t","Type1":"t"}},"bytes":{"path":"bytes","name":"bytes","symbols":{"Buffer":"t","Buffer.Available":"m","Buffer.AvailableBuffer":"m","Buffer.Bytes":"m","Buffer.Cap":"m","Buffer.Grow":"m","Buffer.Len":"m","Buffer.Next":"m","Buffer.Read":"m","Buffer.ReadByte":"m","Buffer.ReadBytes":"m","Buffer.ReadFrom":"m","Buffer.ReadRune":"m","Buffer.ReadString":"m","Buffer.Reset":"m","Buffer.String":"m","Buffer.Truncate":"m","Buffer.UnreadByte":"m","Buffer.UnreadRune":"m","Buffer.Write":"m","Buffer.WriteByte":"m","Buffer.WriteRune":"m","Buffer.WriteString":"m","Buffer.WriteTo":"m","Clone":"f","Compare":"f","Contains":"f","ContainsAny":"f","ContainsFunc":"f","ContainsRune":"f","Count":"f","Cut":"f","CutPrefix":"f","CutSuffix":"f","Equal":"f","EqualFold":"f","ErrTooLarge":"v","Fields":"f","FieldsFunc":"f","FieldsFuncSeq":"f","FieldsSeq":"f","HasPrefix":"f","HasSuffix":"f","Index":"f","IndexAny":"f","IndexByte":"f","IndexFunc":"f","IndexRune":"f","Join":"f","LastIndex":"f","LastIndexAny":"f","LastIndexByte":"f","LastIndexFunc":"f","Lines":"f","Map":"f","MinRead":"c","NewBuffer":"f","NewBufferString":"f","NewReader":"f","Reader":"t","Reader.Len":"m","Reader.Read":"m","Reader.ReadAt":"m","Reader.ReadByte":"m","Reader.ReadRune":"m","Reader.Reset":"m","Reader.Seek":"m","Reader.Size":"m","Reader.UnreadByte":"m","Reader.UnreadRune":"m","Reader.WriteTo":"m","Repeat":"f","Replace":"f","ReplaceAll":"f","Runes":"f","Split":"f","SplitAfter":"f","SplitAfterN":"f","SplitAfterSeq":"f","SplitN":"f","SplitSeq":"f","Title":"f","ToLower":"f","ToLowerSpecial":"f","ToTitle":"f","ToTitleSpecial":"f","ToUpper":"f","ToUpperSpecial":"f","ToValidUTF8":"f","Trim":"f","TrimFunc":"f","TrimLeft":"f","TrimLeftFunc":"f","TrimPrefix":"f","TrimRight":"f","TrimRightFunc":"f","TrimSpace":"f","TrimSuffix":"f"}},"cmp":{"path":"cmp","name":"cmp","symbols":{"Compare":"f","Less":"f","Or":"f","Ordered":"t"}},"compress/bzip2":{"path":"compress/bzip2","name":"bzip2","symbols":{"NewReader":"f","StructuralError":"t","StructuralError.Error":"m"}},"compress/flate":{"path":"compress/flate","name":"flate","symbols":{"BestCompression":"c","BestSpeed":"c","CorruptInputError":"t","CorruptInputError.Error":"m","DefaultCompression":"c","HuffmanOnly":"c","InternalError":"t","InternalError.Error":"m","NewReader":"f","NewReaderDict":"f","NewWriter":"f","NewWriterDict":"f","NoCompression":"c","ReadError":"t","ReadError.Error":"m","Reader":"t","Resetter":"t","WriteError":"t","WriteError.Error":"m","Writer":"t","Writer.Close":"m","Writer.Flush":"m","Writer.Reset":"m","Writer.Write":"m"}},"compress/gzip":{"path":"compress/gzip","name":"gzip","symbols":{"BestCompression":"c","BestSpeed":"c","DefaultCompression":"c","ErrChecksum":"v","ErrHeader":"v","Header":"t","HuffmanOnly":"c","NewReader":"f","NewWriter":"f","NewWriterLevel":"f","NoCompression":"c","Reader":"t","Reader.Close":"m","Reader.Multistream":"m","Reader.Read":"m","Reader.Reset":"m","Writer":"t","Writer.Close":"m","Writer.Flush":"m","Writer.Reset":"m","Writer.Write":"m"}},"compress/lzw":{"path":"compress/lzw","name":"lzw","symbols":{"LSB":"c","MSB":"c","NewReader":"f","NewWriter":"f","Order":"t","Reader":"t","Reader.Close":"m","Reader.Read":"m","Reader.Reset":"m","Writer":"t","Writer.Close":"m","Writer.Reset":"m","Writer.Write":"m"}},"compress/zlib":{"path":"compress/zlib","name":"zlib","symbols":{"BestCompression":"c","BestSpeed":"c","DefaultCompression":"c","ErrChecksum":"v","ErrDictionary":"v","ErrHeader":"v","HuffmanOnly":"c","NewReader":"f","NewReaderDict":"f","NewWriter":"f","NewWriterLevel":"f","NewWriterLevelDict":"f","NoCompression":"c","Resetter":"t","Writer":"t","Writer.Close":"m","Writer.Flush":"m","Writer.Reset":"m","Writer.Write":"m"}},"container/heap":{"path":"container/heap","name":"heap","symbols":{"Fix":"f","Init":"f","Interface":"t","Pop":"f","Push":"f","Remove":"f"}},"container/list":{"path":"container/list","name":"list","symbols":{"Element":"t","Element.Next":"m","Element.Prev":"m","List":"t","List.Back":"m","List.Front":"m","List.Init":"m","List.InsertAfter":"m","List.InsertBefore":"m","List.Len":"m","List.MoveAfter":"m","List.MoveBefore":"m","List.MoveToBack":"m","List.MoveToFront":"m","List.PushBack":"m","List.PushBackList":"m","List.PushFront":"m","List.PushFrontList":"m","List.Remove":"m","New":"f"}},"container/ring":{"path":"container/ring","name":"ring","symbols":{"New":"f","Ring":"t","Ring.Do":"m","Ring.Len":"m","Ring.Link":"m","Ring.Move":"m","Ring.Next":"m","Ring.Prev":"m","Ring.Unlink":"m"}},"context":{"path":"context","name":"context","symbols":{"AfterFunc":"f","Background":"f","CancelCauseFunc":"t","CancelFunc":"t","Canceled":"v","Cause":"f","Context":"t","DeadlineExceeded":"v","TODO":"f","WithCancel":"f","WithCancelCause":"f","WithDeadline":"f","WithDeadlineCause":"f","WithTimeout":"f","WithTimeoutCause":"f","WithValue":"f","WithoutCancel":"f"}},"crypto":{"path":"crypto","name":"crypto","symbols":{"BLAKE2b_256":"c","BLAKE2b_384":"c","BLAKE2b_512":"c","BLAKE2s_256":"c","Decrypter":"t","DecrypterOpts":"t","Hash":"t","Hash.Available":"m","Hash.HashFunc":"m","Hash.New":"m","Hash.Size":"m","Hash.String":"m","MD4":"c","MD5":"c","MD5SHA1":"c","MessageSigner":"t","PrivateKey":"t","PublicKey":"t","RIPEMD160":"c","RegisterHash":"f","SHA1":"c","SHA224":"c","SHA256":"c","SHA384":"c","SHA3_224":"c","SHA3_256":"c","SHA3_384":"c","SHA3_512":"c","SHA512":"c","SHA512_224":"c","SHA512_256":"c","SignMessage":"f","Signer":"t","SignerOpts":"t"}},"crypto/aes":{"path":"crypto/aes","name":"aes","symbols":{"BlockSize":"c","KeySizeError":"t","KeySizeError.Error":"m","NewCipher":"f"}},"crypto/cipher":{"path":"crypto/cipher","name":"cipher","symbols":{"AEAD":"t","Block":"t","BlockMode":"t","NewCBCDecrypter":"f","NewCBCEncrypter":"f","NewCFBDecrypter":"f","NewCFBEncrypter":"f","NewCTR":"f","NewGCM":"f","NewGCMWithNonceSize":"f","NewGCMWithRandomNonce":"f","NewGCMWithTagSize":"f","NewOFB":"f","Stream":"t","StreamReader":"t","StreamReader.Read":"m","StreamWriter":"t","StreamWriter.Close":"m","StreamWriter.Write":"m"}},"crypto/des":{"path":"crypto/des","name":"des","symbols":{"BlockSize":"c","KeySizeError":"t","KeySizeError.Error":"m","NewCipher":"f","NewTripleDESCipher":"f"}},"crypto/dsa":{"path":"crypto/dsa","name":"dsa","symbols":{"ErrInvalidPublicKey":"v","GenerateKey":"f","GenerateParameters":"f","L1024N160":"c","L2048N224":"c","L2048N256":"c","L3072N256":"c","ParameterSizes":"t","Parameters":"t","PrivateKey":"t","PublicKey":"t","Sign":"f","Verify":"f"}},"crypto/ecdh":{"path":"crypto/ecdh","name":"ecdh","symbols":{"Curve":"t","P256":"f","P384":"f","P521":"f","PrivateKey":"t","PrivateKey.Bytes":"m","PrivateKey.Curve":"m","PrivateKey.ECDH":"m","PrivateKey.Equal":"m","PrivateKey.Public":"m","PrivateKey.PublicKey":"m","PublicKey":"t","PublicKey.Bytes":"m","PublicKey.Curve":"m","PublicKey.Equal":"m","X25519":"f"}},"crypto/ecdsa":{"path":"crypto/ecdsa","name":"ecdsa","symbols":{"GenerateKey":"f","ParseRawPrivateKey":"f","ParseUncompressedPublicKey":"f","PrivateKey":"t","PrivateKey.Bytes":"m","PrivateKey.ECDH":"m","PrivateKey.Equal":"m","PrivateKey.Public":"m","PrivateKey.Sign":"m","PublicKey":"t","PublicKey.Bytes":"m","PublicKey.ECDH":"m","PublicKey.Equal":"m","Sign":"f","SignASN1":"f","Verify":"f","VerifyASN1":"f"}},"crypto/ed25519":{"path":"crypto/ed25519","name":"ed25519","symbols":{"GenerateKey":"f","NewKeyFromSeed":"f","Options":"t","Options.HashFunc":"m","PrivateKey":"t","PrivateKey.Equal":"m","PrivateKey.Public":"m","PrivateKey.Seed":"m","PrivateKey.Sign":"m","PrivateKeySize":"c","PublicKey":"t","PublicKey.Equal":"m","PublicKeySize":"c","SeedSize":"c","Sign":"f","SignatureSize":"c","Verify":"f","VerifyWithOptions":"f"}},"crypto/elliptic":{"path":"crypto/elliptic","name":"elliptic","symbols":{"Curve":"t","CurveParams":"t","CurveParams.Add":"m","CurveParams.Double":"m","CurveParams.IsOnCurve":"m","CurveParams.Params":"m","CurveParams.ScalarBaseMult":"m","CurveParams.ScalarMult":"m","GenerateKey":"f","Marshal":"f","MarshalCompressed":"f","P224":"f","P256":"f","P384":"f","P521":"f","Unmarshal":"f","UnmarshalCompressed":"f"}},"crypto/fips140":{"path":"crypto/fips140","name":"fips140","symbols":{"Enabled":"f"}},"crypto/hkdf":{"path":"crypto/hkdf","name":"hkdf","symbols":{"Expand":"f","Extract":"f","Key":"f"}},"crypto/hmac":{"path":"crypto/hmac","name":"hmac","symbols":{"Equal":"f","New":"f"}},"crypto/md5":{"path":"crypto/md5","name":"md5","symbols":{"BlockSize":"c","New":"f","Size":"c","Sum":"f"}},"crypto/mlkem":{"path":"crypto/mlkem","name":"mlkem","symbols":{"CiphertextSize1024":"c","CiphertextSize768":"c","DecapsulationKey1024":"t","DecapsulationKey1024.Bytes":"m","DecapsulationKey1024.Decapsulate":"m","DecapsulationKey1024.EncapsulationKey":"m","DecapsulationKey768":"t","DecapsulationKey768.Bytes":"m","DecapsulationKey768.Decapsulate":"m","DecapsulationKey768.EncapsulationKey":"m","EncapsulationKey1024":"t","EncapsulationKey1024.Bytes":"m","EncapsulationKey1024.Encapsulate":"m","EncapsulationKey768":"t","EncapsulationKey768.Bytes":"m","EncapsulationKey768.Encapsulate":"m","EncapsulationKeySize1024":"c","EncapsulationKeySize768":"c","GenerateKey1024":"f","GenerateKey768":"f","NewDecapsulationKey1024":"f","NewDecapsulationKey768":"f","NewEncapsulationKey1024":"f","NewEncapsulationKey768":"f","SeedSize":"c","SharedKeySize":"c"}},"crypto/pbkdf2":{"path":"crypto/pbkdf2","name":"pbkdf2","symbols":{"Key":"f"}},"crypto/rand":{"path":"crypto/rand","name":"rand","symbols":{"Int":"f","Prime":"f","Read":"f","Reader":"v","Text":"f"}},"crypto/rc4":{"path":"crypto/rc4","name":"rc4","symbols":{"Cipher":"t","Cipher.Reset":"m","Cipher.XORKeyStream":"m","KeySizeError":"t","KeySizeError.Error":"m","NewCipher":"f"}},"crypto/rsa":{"path":"crypto/rsa","name":"rsa","symbols":{"CRTValue":"t","DecryptOAEP":"f","DecryptPKCS1v15":"f","DecryptPKCS1v15SessionKey":"f","EncryptOAEP":"f","EncryptPKCS1v15":"f","ErrDecryption":"v","ErrMessageTooLong":"v","ErrVerification":"v","GenerateKey":"f","GenerateMultiPrimeKey":"f","OAEPOptions":"t","PKCS1v15DecryptOptions":"t","PSSOptions":"t","PSSOptions.HashFunc":"m","PSSSaltLengthAuto":"c","PSSSaltLengthEqualsHash":"c","PrecomputedValues":"t","PrivateKey":"t","PrivateKey.Decrypt":"m","PrivateKey.Equal":"m","PrivateKey.Precompute":"m","PrivateKey.Public":"m","PrivateKey.Sign":"m","PrivateKey.Validate":"m","PublicKey":"t","PublicKey.Equal":"m","PublicKey.Size":"m","SignPKCS1v15":"f","SignPSS":"f","VerifyPKCS1v15":"f","VerifyPSS":"f"}},"crypto/sha1":{"path":"crypto/sha1","name":"sha1","symbols":{"BlockSize":"c","New":"f","Size":"c","Sum":"f"}},"crypto/sha256":{"path":"crypto/sha256","name":"sha256","symbols":{"BlockSize":"c","New":"f","New224":"f","Size":"c","Size224":"c","Sum224":"f","Sum256":"f"}},"crypto/sha3":{"path":"crypto/sha3","name":"sha3","symbols":{"New224":"f","New256":"f","New384":"f","New512":"f","NewCSHAKE128":"f","NewCSHAKE256":"f","NewSHAKE128":"f","NewSHAKE256":"f","SHA3":"t","SHA3.AppendBinary":"m","SHA3.BlockSize":"m","SHA3.Clone":"m","SHA3.MarshalBinary":"m","SHA3.Reset":"m","SHA3.Size":"m","SHA3.Sum":"m","SHA3.UnmarshalBinary":"m","SHA3.Write":"m","SHAKE":"t","SHAKE.AppendBinary":"m","SHAKE.BlockSize":"m","SHAKE.MarshalBinary":"m","SHAKE.Read":"m","SHAKE.Reset":"m","SHAKE.UnmarshalBinary":"m","SHAKE.Write":"m","Sum224":"f","Sum256":"f","Sum384":"f","Sum512":"f","SumSHAKE128":"f","SumSHAKE256":"f"}},"crypto/sha512":{"path":"crypto/sha512","name":"sha512","symbols":{"BlockSize":"c","New":"f","New384":"f","New512_224":"f","New512_256":"f","Size":"c","Size224":"c","Size256":"c","Size384":"c","Sum384":"f","Sum512":"f","Sum512_224":"f","Sum512_256":"f"}},"crypto/subtle":{"path":"crypto/subtle","name":"subtle","symbols":{"ConstantTimeByteEq":"f","ConstantTimeCompare":"f","ConstantTimeCopy":"f","ConstantTimeEq":"f","ConstantTimeLessOrEq":"f","ConstantTimeSelect":"f","WithDataIndependentTiming":"f","XORBytes":"f"}},"crypto/tls":{"path":"crypto/tls","name":"tls","symbols":{"AlertError":"t","AlertError.Error":"m","Certificate":"t","CertificateRequestInfo":"t","CertificateRequestInfo.Context":"m","CertificateRequestInfo.SupportsCertificate":"m","CertificateVerificationError":"t","CertificateVerificationError.Error":"m","CertificateVerificationError.Unwrap":"m","CipherSuite":"t","CipherSuiteName":"f","CipherSuites":"f","Client":"f","ClientAuthType":"t","ClientAuthType.String":"m","ClientHelloInfo":"t","ClientHelloInfo.Context":"m","ClientHelloInfo.SupportsCertificate":"m","ClientSessionCache":"t","ClientSessionState":"t","ClientSessionState.ResumptionState":"m","Config":"t","Config.BuildNameToCertificate":"m","Config.Clone":"m","Config.DecryptTicket":"m","Config.EncryptTicket":"m","Config.SetSessionTicketKeys":"m","Conn":"t","Conn.Close":"m","Conn.CloseWrite":"m","Conn.ConnectionState":"m","Conn.Handshake":"m","Conn.HandshakeContext":"m","Conn.LocalAddr":"m","Conn.NetConn":"m","Conn.OCSPResponse":"m","Conn.Read":"m","Conn.RemoteAddr":"m","Conn.SetDeadline":"m","Conn.SetReadDeadline":"m","Conn.SetWriteDeadline":"m","Conn.VerifyHostname":"m","Conn.Write":"m","ConnectionState":"t","ConnectionState.ExportKeyingMaterial":"m","CurveID":"t","CurveID.String":"m","CurveP256":"c","CurveP384":"c","CurveP521":"c","Dial":"f","DialWithDialer":"f","Dialer":"t","Dialer.Dial":"m","Dialer.DialContext":"m","ECDSAWithP256AndSHA256":"c","ECDSAWithP384AndSHA384":"c","ECDSAWithP521AndSHA512":"c","ECDSAWithSHA1":"c","ECHRejectionError":"t","ECHRejectionError.Error":"m","Ed25519":"c","EncryptedClientHelloKey":"t","InsecureCipherSuites":"f","Listen":"f","LoadX509KeyPair":"f","NewLRUClientSessionCache":"f","NewListener":"f","NewResumptionState":"f","NoClientCert":"c","PKCS1WithSHA1":"c","PKCS1WithSHA256":"c","PKCS1WithSHA384":"c","PKCS1WithSHA512":"c","PSSWithSHA256":"c","PSSWithSHA384":"c","PSSWithSHA512":"c","ParseSessionState":"f","QUICClient":"f","QUICConfig":"t","QUICConn":"t","QUICConn.Close":"m","QUICConn.ConnectionState":"m","QUICConn.HandleData":"m","QUICConn.NextEvent":"m","QUICConn.SendSessionTicket":"m","QUICConn.SetTransportParameters":"m","QUICConn.Start":"m","QUICConn.StoreSession":"m","QUICEncryptionLevel":"t","QUICEncryptionLevel.String":"m","QUICEncryptionLevelApplication":"c","QUICEncryptionLevelEarly":"c","QUICEncryptionLevelHandshake":"c","QUICEncryptionLevelInitial":"c","QUICEvent":"t","QUICEventKind":"t","QUICHandshakeDone":"c","QUICNoEvent":"c","QUICRejectedEarlyData":"c","QUICResumeSession":"c","QUICServer":"f","QUICSessionTicketOptions":"t","QUICSetReadSecret":"c","QUICSetWriteSecret":"c","QUICStoreSession":"c","QUICTransportParameters":"c","QUICTransportParametersRequired":"c","QUICWriteData":"c","RecordHeaderError":"t","RecordHeaderError.Error":"m","RenegotiateFreelyAsClient":"c","RenegotiateNever":"c","RenegotiateOnceAsClient":"c","RenegotiationSupport":"t","RequestClientCert":"c","RequireAndVerifyClientCert":"c","RequireAnyClientCert":"c","Server":"f","SessionState":"t","SessionState.Bytes":"m","SignatureScheme":"t","SignatureScheme.String":"m","TLS_AES_128_GCM_SHA256":"c","TLS_AES_256_GCM_SHA384":"c","TLS_CHACHA20_POLY1305_SHA256":"c","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA":"c","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256":"c","TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256":"c","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA":"c","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384":"c","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305":"c","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256":"c","TLS_ECDHE_ECDSA_WITH_RC4_128_SHA":"c","TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA":"c","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA":"c","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256":"c","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256":"c","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA":"c","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384":"c","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305":"c","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256":"c","TLS_ECDHE_RSA_WITH_RC4_128_SHA":"c","TLS_FALLBACK_SCSV":"c","TLS_RSA_WITH_3DES_EDE_CBC_SHA":"c","TLS_RSA_WITH_AES_128_CBC_SHA":"c","TLS_RSA_WITH_AES_128_CBC_SHA256":"c","TLS_RSA_WITH_AES_128_GCM_SHA256":"c","TLS_RSA_WITH_AES_256_CBC_SHA":"c","TLS_RSA_WITH_AES_256_GCM_SHA384":"c","TLS_RSA_WITH_RC4_128_SHA":"c","VerifyClientCertIfGiven":"c","VersionName":"f","VersionSSL30":"c","VersionTLS10":"c","VersionTLS11":"c","VersionTLS12":"c","VersionTLS13":"c","X25519":"c","X25519MLKEM768":"c","X509KeyPair":"f"}},"crypto/x509":{"path":"crypto/x509","name":"x509","symbols":{"CANotAuthorizedForExtKeyUsage":"c","CANotAuthorizedForThisName":"c","CertPool":"t","CertPool.AddCert":"m","CertPool.AddCertWithConstraint":"m","CertPool.AppendCertsFromPEM":"m","CertPool.Clone":"m","CertPool.Equal":"m","CertPool.Subjects":"m","Certificate":"t","Certificate.CheckCRLSignature":"m","Certificate.CheckSignature":"m","Certificate.CheckSignatureFrom":"m","Certificate.CreateCRL":"m","Certificate.Equal":"m","Certificate.Verify":"m","Certificate.VerifyHostname":"m","CertificateInvalidError":"t","CertificateInvalidError.Error":"m","CertificateRequest":"t","CertificateRequest.CheckSignature":"m","ConstraintViolationError":"t","ConstraintViolationError.Error":"m","CreateCertificate":"f","CreateCertificateRequest":"f","CreateRevocationList":"f","DSA":"c","DSAWithSHA1":"c","DSAWithSHA256":"c","DecryptPEMBlock":"f","ECDSA":"c","ECDSAWithSHA1":"c","ECDSAWithSHA256":"c","ECDSAWithSHA384":"c","ECDSAWithSHA512":"c","Ed25519":"c","EncryptPEMBlock":"f","ErrUnsupportedAlgorithm":"v","Expired":"c","ExtKeyUsage":"t","ExtKeyUsageAny":"c","ExtKeyUsageClientAuth":"c","ExtKeyUsageCodeSigning":"c","ExtKeyUsageEmailProtection":"c","ExtKeyUsageIPSECEndSystem":"c","ExtKeyUsageIPSECTunnel":"c","ExtKeyUsageIPSECUser":"c","ExtKeyUsageMicrosoftCommercialCodeSigning":"c","ExtKeyUsageMicrosoftKernelCodeSigning":"c","ExtKeyUsageMicrosoftServerGatedCrypto":"c","ExtKeyUsageNetscapeServerGatedCrypto":"c","ExtKeyUsageOCSPSigning":"c","ExtKeyUsageServerAuth":"c","ExtKeyUsageTimeStamping":"c","HostnameError":"t","HostnameError.Error":"m","IncompatibleUsage":"c","IncorrectPasswordError":"v","InsecureAlgorithmError":"t","InsecureAlgorithmError.Error":"m","InvalidReason":"t","IsEncryptedPEMBlock":"f","KeyUsage":"t","KeyUsageCRLSign":"c","KeyUsageCertSign":"c","KeyUsageContentCommitment":"c","KeyUsageDataEncipherment":"c","KeyUsageDecipherOnly":"c","KeyUsageDigitalSignature":"c","KeyUsageEncipherOnly":"c","KeyUsageKeyAgreement":"c","KeyUsageKeyEncipherment":"c","MD2WithRSA":"c","MD5WithRSA":"c","MarshalECPrivateKey":"f","MarshalPKCS1PrivateKey":"f","MarshalPKCS1PublicKey":"f","MarshalPKCS8PrivateKey":"f","MarshalPKIXPublicKey":"f","NameConstraintsWithoutSANs":"c","NameMismatch":"c","NewCertPool":"f","NoValidChains":"c","NotAuthorizedToSign":"c","OID":"t","OID.AppendBinary":"m","OID.AppendText":"m","OID.Equal":"m","OID.EqualASN1OID":"m","OID.MarshalBinary":"m","OID.MarshalText":"m","OID.String":"m","OID.UnmarshalBinary":"m","OID.UnmarshalText":"m","OIDFromInts":"f","PEMCipher":"t","PEMCipher3DES":"c","PEMCipherAES128":"c","PEMCipherAES192":"c","PEMCipherAES256":"c","PEMCipherDES":"c","ParseCRL":"f","ParseCertificate":"f","ParseCertificateRequest":"f","ParseCertificates":"f","ParseDERCRL":"f","ParseECPrivateKey":"f","ParseOID":"f","ParsePKCS1PrivateKey":"f","ParsePKCS1PublicKey":"f","ParsePKCS8PrivateKey":"f","ParsePKIXPublicKey":"f","ParseRevocationList":"f","PolicyMapping":"t","PublicKeyAlgorithm":"t","PublicKeyAlgorithm.String":"m","PureEd25519":"c","RSA":"c","RevocationList":"t","RevocationList.CheckSignatureFrom":"m","RevocationListEntry":"t","SHA1WithRSA":"c","SHA256WithRSA":"c","SHA256WithRSAPSS":"c","SHA384WithRSA":"c","SHA384WithRSAPSS":"c","SHA512WithRSA":"c","SHA512WithRSAPSS":"c","SetFallbackRoots":"f","SignatureAlgorithm":"t","SignatureAlgorithm.String":"m","SystemCertPool":"f","SystemRootsError":"t","SystemRootsError.Error":"m","SystemRootsError.Unwrap":"m","TooManyConstraints":"c","TooManyIntermediates":"c","UnconstrainedName":"c","UnhandledCriticalExtension":"t","UnhandledCriticalExtension.Error":"m","UnknownAuthorityError":"t","UnknownAuthorityError.Error":"m","UnknownPublicKeyAlgorithm":"c","UnknownSignatureAlgorithm":"c","VerifyOptions":"t"}},"crypto/x509/pkix":{"path":"crypto/x509/pkix","name":"pkix","symbols":{"AlgorithmIdentifier":"t","AttributeTypeAndValue":"t","AttributeTypeAndValueSET":"t","CertificateList":"t","CertificateList.HasExpired":"m","Extension":"t","Name":"t","Name.FillFromRDNSequence":"m","Name.String":"m","Name.ToRDNSequence":"m","RDNSequence":"t","RDNSequence.String":"m","RelativeDistinguishedNameSET":"t","RevokedCertificate":"t","TBSCertificateList":"t"}},"database/sql":{"path":"database/sql","name":"sql","symbols":{"ColumnType":"t","ColumnType.DatabaseTypeName":"m","ColumnType.DecimalSize":"m","ColumnType.Length":"m","ColumnType.Name":"m","ColumnType.Nullable":"m","ColumnType.ScanType":"m","Conn":"t","Conn.BeginTx":"m","Conn.Close":"m","Conn.ExecContext":"m","Conn.PingContext":"m","Conn.PrepareContext":"m","Conn.QueryContext":"m","Conn.QueryRowContext":"m","Conn.Raw":"m","DB":"t","DB.Begin":"m","DB.BeginTx":"m","DB.Close":"m","DB.Conn":"m","DB.Driver":"m","DB.Exec":"m","DB.ExecContext":"m","DB.Ping":"m","DB.PingContext":"m","DB.Prepare":"m","DB.PrepareContext":"m","DB.Query":"m","DB.QueryContext":"m","DB.QueryRow":"m","DB.QueryRowContext":"m","DB.SetConnMaxIdleTime":"m","DB.SetConnMaxLifetime":"m","DB.SetMaxIdleConns":"m","DB.SetMaxOpenConns":"m","DB.Stats":"m","DBStats":"t","Drivers":"f","ErrConnDone":"v","ErrNoRows":"v","ErrTxDone":"v","IsolationLevel":"t","IsolationLevel.String":"m","LevelDefault":"c","LevelLinearizable":"c","LevelReadCommitted":"c","LevelReadUncommitted":"c","LevelRepeatableRead":"c","LevelSerializable":"c","LevelSnapshot":"c","LevelWriteCommitted":"c","Named":"f","NamedArg":"t","Null":"t","NullBool":"t","NullBool.Scan":"m","NullBool.Value":"m","NullByte":"t","NullByte.Scan":"m","NullByte.Value":"m","NullFloat64":"t","NullFloat64.Scan":"m","NullFloat64.Value":"m","NullInt16":"t","NullInt16.Scan":"m","NullInt16.Value":"m","NullInt32":"t","NullInt32.Scan":"m","NullInt32.Value":"m","NullInt64":"t","NullInt64.Scan":"m","NullInt64.Value":"m","NullString":"t","NullString.Scan":"m","NullString.Value":"m","NullTime":"t","NullTime.Scan":"m","NullTime.Value":"m","Open":"f","OpenDB":"f","Out":"t","RawBytes":"t","Register":"f","Result":"t","Row":"t","Row.Err":"m","Row.Scan":"m","Rows":"t","Rows.Close":"m","Rows.ColumnTypes":"m","Rows.Columns":"m","Rows.Err":"m","Rows.Next":"m","Rows.NextResultSet":"m","Rows.Scan":"m","Scanner":"t","Stmt":"t","Stmt.Close":"m","Stmt.Exec":"m","Stmt.ExecContext":"m","Stmt.Query":"m","Stmt.QueryContext":"m","Stmt.QueryRow":"m","Stmt.QueryRowContext":"m","Tx":"t","Tx.Commit":"m","Tx.Exec":"m","Tx.ExecContext":"m","Tx.Prepare":"m","Tx.PrepareContext":"m","Tx.Query":"m","Tx.QueryContext":"m","Tx.QueryRow":"m","Tx.QueryRowContext":"m","Tx.Rollback":"m","Tx.Stmt":"m","Tx.StmtContext":"m","TxOptions":"t"}},"database/sql/driver":{"path":"database/sql/driver","name":"driver","symbols":{"Bool":"v","ColumnConverter":"t","Conn":"t","ConnBeginTx":"t","ConnPrepareContext":"t","Connector":"t","DefaultParameterConverter":"v","Driver":"t","DriverContext":"t","ErrBadConn":"v","ErrRemoveArgument":"v","ErrSkip":"v","Execer":"t","ExecerContext":"t","Int32":"v","IsScanValue":"f","IsValue":"f","IsolationLevel":"t","NamedValue":"t","NamedValueChecker":"t","NotNull":"t","NotNull.ConvertValue":"m","Null":"t","Null.ConvertValue":"m","Pinger":"t","Queryer":"t","QueryerContext":"t","Result":"t","ResultNoRows":"v","Rows":"t","RowsAffected":"t","RowsAffected.LastInsertId":"m","RowsAffected.RowsAffected":"m","RowsColumnTypeDatabaseTypeName":"t","RowsColumnTypeLength":"t","RowsColumnTypeNullable":"t","RowsColumnTypePrecisionScale":"t","RowsColumnTypeScanType":"t","RowsNextResultSet":"t","SessionResetter":"t","Stmt":"t","StmtExecContext":"t","StmtQueryContext":"t","String":"v","Tx":"t","TxOptions":"t","Validator":"t","Value":"t","ValueConverter":"t","Valuer":"t"}},"debug/buildinfo":{"path":"debug/buildinfo","name":"buildinfo","symbols":{"BuildInfo":"t","Read":"f","ReadFile":"f"}},"debug/dwarf":{"path":"debug/dwarf","name":"dwarf","symbols":{"AddrType":"t","ArrayType":"t","ArrayType.Size":"m","ArrayType.String":"m","Attr":"t","Attr.GoString":"m","Attr.String":"m","AttrAbstractOrigin":"c","AttrAccessibility":"c","AttrAddrBase":"c","AttrAddrClass":"c","AttrAlignment":"c","AttrAllocated":"c","AttrArtificial":"c","AttrAssociated":"c","AttrBaseTypes":"c","AttrBinaryScale":"c","AttrBitOffset":"c","AttrBitSize":"c","AttrByteSize":"c","AttrCallAllCalls":"c","AttrCallAllSourceCalls":"c","AttrCallAllTailCalls":"c","AttrCallColumn":"c","AttrCallDataLocation":"c","AttrCallDataValue":"c","AttrCallFile":"c","AttrCallLine":"c","AttrCallOrigin":"c","AttrCallPC":"c","AttrCallParameter":"c","AttrCallReturnPC":"c","AttrCallTailCall":"c","AttrCallTarget":"c","AttrCallTargetClobbered":"c","AttrCallValue":"c","AttrCalling":"c","AttrCommonRef":"c","AttrCompDir":"c","AttrConstExpr":"c","AttrConstValue":"c","AttrContainingType":"c","AttrCount":"c","AttrDataBitOffset":"c","AttrDataLocation":"c","AttrDataMemberLoc":"c","AttrDecimalScale":"c","AttrDecimalSign":"c","AttrDeclColumn":"c","AttrDeclFile":"c","AttrDeclLine":"c","AttrDeclaration":"c","AttrDefaultValue":"c","AttrDefaulted":"c","AttrDeleted":"c","AttrDescription":"c","AttrDigitCount":"c","AttrDiscr":"c","AttrDiscrList":"c","AttrDiscrValue":"c","AttrDwoName":"c","AttrElemental":"c","AttrEncoding":"c","AttrEndianity":"c","AttrEntrypc":"c","AttrEnumClass":"c","AttrExplicit":"c","AttrExportSymbols":"c","AttrExtension":"c","AttrExternal":"c","AttrFrameBase":"c","AttrFriend":"c","AttrHighpc":"c","AttrIdentifierCase":"c","AttrImport":"c","AttrInline":"c","AttrIsOptional":"c","AttrLanguage":"c","AttrLinkageName":"c","AttrLocation":"c","AttrLoclistsBase":"c","AttrLowerBound":"c","AttrLowpc":"c","AttrMacroInfo":"c","AttrMacros":"c","AttrMainSubprogram":"c","AttrMutable":"c","AttrName":"c","AttrNamelistItem":"c","AttrNoreturn":"c","AttrObjectPointer":"c","AttrOrdering":"c","AttrPictureString":"c","AttrPriority":"c","AttrProducer":"c","AttrPrototyped":"c","AttrPure":"c","AttrRanges":"c","AttrRank":"c","AttrRecursive":"c","AttrReference":"c","AttrReturnAddr":"c","AttrRnglistsBase":"c","AttrRvalueReference":"c","AttrSegment":"c","AttrSibling":"c","AttrSignature":"c","AttrSmall":"c","AttrSpecification":"c","AttrStartScope":"c","AttrStaticLink":"c","AttrStmtList":"c","AttrStrOffsetsBase":"c","AttrStride":"c","AttrStrideSize":"c","AttrStringLength":"c","AttrStringLengthBitSize":"c","AttrStringLengthByteSize":"c","AttrThreadsScaled":"c","AttrTrampoline":"c","AttrType":"c","AttrUpperBound":"c","AttrUseLocation":"c","AttrUseUTF8":"c","AttrVarParam":"c","AttrVirtuality":"c","AttrVisibility":"c","AttrVtableElemLoc":"c","BasicType":"t","BasicType.Basic":"m","BasicType.String":"m","BoolType":"t","CharType":"t","Class":"t","Class.GoString":"m","Class.String":"m","ClassAddrPtr":"c","ClassAddress":"c","ClassBlock":"c","ClassConstant":"c","ClassExprLoc":"c","ClassFlag":"c","ClassLinePtr":"c","ClassLocList":"c","ClassLocListPtr":"c","ClassMacPtr":"c","ClassRangeListPtr":"c","ClassReference":"c","ClassReferenceAlt":"c","ClassReferenceSig":"c","ClassRngList":"c","ClassRngListsPtr":"c","ClassStrOffsetsPtr":"c","ClassString":"c","ClassStringAlt":"c","ClassUnknown":"c","CommonType":"t","CommonType.Common":"m","CommonType.Size":"m","ComplexType":"t","Data":"t","Data.AddSection":"m","Data.AddTypes":"m","Data.LineReader":"m","Data.Ranges":"m","Data.Reader":"m","Data.Type":"m","DecodeError":"t","DecodeError.Error":"m","DotDotDotType":"t","DotDotDotType.String":"m","Entry":"t","Entry.AttrField":"m","Entry.Val":"m","EnumType":"t","EnumType.String":"m","EnumValue":"t","ErrUnknownPC":"v","Field":"t","FloatType":"t","FuncType":"t","FuncType.String":"m","IntType":"t","LineEntry":"t","LineFile":"t","LineReader":"t","LineReader.Files":"m","LineReader.Next":"m","LineReader.Reset":"m","LineReader.Seek":"m","LineReader.SeekPC":"m","LineReader.Tell":"m","LineReaderPos":"t","New":"f","Offset":"t","PtrType":"t","PtrType.String":"m","QualType":"t","QualType.Size":"m","QualType.String":"m","Reader":"t","Reader.AddressSize":"m","Reader.ByteOrder":"m","Reader.Next":"m","Reader.Seek":"m","Reader.SeekPC":"m","Reader.SkipChildren":"m","StructField":"t","StructType":"t","StructType.Defn":"m","StructType.String":"m","Tag":"t","Tag.GoString":"m","Tag.String":"m","TagAccessDeclaration":"c","TagArrayType":"c","TagAtomicType":"c","TagBaseType":"c","TagCallSite":"c","TagCallSiteParameter":"c","TagCatchDwarfBlock":"c","TagClassType":"c","TagCoarrayType":"c","TagCommonDwarfBlock":"c","TagCommonInclusion":"c","TagCompileUnit":"c","TagCondition":"c","TagConstType":"c","TagConstant":"c","TagDwarfProcedure":"c","TagDynamicType":"c","TagEntryPoint":"c","TagEnumerationType":"c","TagEnumerator":"c","TagFileType":"c","TagFormalParameter":"c","TagFriend":"c","TagGenericSubrange":"c","TagImmutableType":"c","TagImportedDeclaration":"c","TagImportedModule":"c","TagImportedUnit":"c","TagInheritance":"c","TagInlinedSubroutine":"c","TagInterfaceType":"c","TagLabel":"c","TagLexDwarfBlock":"c","TagMember":"c","TagModule":"c","TagMutableType":"c","TagNamelist":"c","TagNamelistItem":"c","TagNamespace":"c","TagPackedType":"c","TagPartialUnit":"c","TagPointerType":"c","TagPtrToMemberType":"c","TagReferenceType":"c","TagRestrictType":"c","TagRvalueReferenceType":"c","TagSetType":"c","TagSharedType":"c","TagSkeletonUnit":"c","TagStringType":"c","TagStructType":"c","TagSubprogram":"c","TagSubrangeType":"c","TagSubroutineType":"c","TagTemplateAlias":"c","TagTemplateTypeParameter":"c","TagTemplateValueParameter":"c","TagThrownType":"c","TagTryDwarfBlock":"c","TagTypeUnit":"c","TagTypedef":"c","TagUnionType":"c","TagUnspecifiedParameters":"c","TagUnspecifiedType":"c","TagVariable":"c","TagVariant":"c","TagVariantPart":"c","TagVolatileType":"c","TagWithStmt":"c","Type":"t","TypedefType":"t","TypedefType.Size":"m","TypedefType.String":"m","UcharType":"t","UintType":"t","UnspecifiedType":"t","UnsupportedType":"t","UnsupportedType.String":"m","VoidType":"t","VoidType.String":"m"}},"debug/elf":{"path":"debug/elf","name":"elf","symbols":{"ARM_MAGIC_TRAMP_NUMBER":"c","COMPRESS_HIOS":"c","COMPRESS_HIPROC":"c","COMPRESS_LOOS":"c","COMPRESS_LOPROC":"c","COMPRESS_ZLIB":"c","COMPRESS_ZSTD":"c","Chdr32":"t","Chdr64":"t","Class":"t","Class.GoString":"m","Class.String":"m","CompressionType":"t","CompressionType.GoString":"m","CompressionType.String":"m","DF_1_CONFALT":"c","DF_1_DIRECT":"c","DF_1_DISPRELDNE":"c","DF_1_DISPRELPND":"c","DF_1_EDITED":"c","DF_1_ENDFILTEE":"c","DF_1_GLOBAL":"c","DF_1_GLOBAUDIT":"c","DF_1_GROUP":"c","DF_1_IGNMULDEF":"c","DF_1_INITFIRST":"c","DF_1_INTERPOSE":"c","DF_1_KMOD":"c","DF_1_LOADFLTR":"c","DF_1_NOCOMMON":"c","DF_1_NODEFLIB":"c","DF_1_NODELETE":"c","DF_1_NODIRECT":"c","DF_1_NODUMP":"c","DF_1_NOHDR":"c","DF_1_NOKSYMS":"c","DF_1_NOOPEN":"c","DF_1_NORELOC":"c","DF_1_NOW":"c","DF_1_ORIGIN":"c","DF_1_PIE":"c","DF_1_SINGLETON":"c","DF_1_STUB":"c","DF_1_SYMINTPOSE":"c","DF_1_TRANS":"c","DF_1_WEAKFILTER":"c","DF_BIND_NOW":"c","DF_ORIGIN":"c","DF_STATIC_TLS":"c","DF_SYMBOLIC":"c","DF_TEXTREL":"c","DT_ADDRRNGHI":"c","DT_ADDRRNGLO":"c","DT_AUDIT":"c","DT_AUXILIARY":"c","DT_BIND_NOW":"c","DT_CHECKSUM":"c","DT_CONFIG":"c","DT_DEBUG":"c","DT_DEPAUDIT":"c","DT_ENCODING":"c","DT_FEATURE":"c","DT_FILTER":"c","DT_FINI":"c","DT_FINI_ARRAY":"c","DT_FINI_ARRAYSZ":"c","DT_FLAGS":"c","DT_FLAGS_1":"c","DT_GNU_CONFLICT":"c","DT_GNU_CONFLICTSZ":"c","DT_GNU_HASH":"c","DT_GNU_LIBLIST":"c","DT_GNU_LIBLISTSZ":"c","DT_GNU_PRELINKED":"c","DT_HASH":"c","DT_HIOS":"c","DT_HIPROC":"c","DT_INIT":"c","DT_INIT_ARRAY":"c","DT_INIT_ARRAYSZ":"c","DT_JMPREL":"c","DT_LOOS":"c","DT_LOPROC":"c","DT_MIPS_AUX_DYNAMIC":"c","DT_MIPS_BASE_ADDRESS":"c","DT_MIPS_COMPACT_SIZE":"c","DT_MIPS_CONFLICT":"c","DT_MIPS_CONFLICTNO":"c","DT_MIPS_CXX_FLAGS":"c","DT_MIPS_DELTA_CLASS":"c","DT_MIPS_DELTA_CLASSSYM":"c","DT_MIPS_DELTA_CLASSSYM_NO":"c","DT_MIPS_DELTA_CLASS_NO":"c","DT_MIPS_DELTA_INSTANCE":"c","DT_MIPS_DELTA_INSTANCE_NO":"c","DT_MIPS_DELTA_RELOC":"c","DT_MIPS_DELTA_RELOC_NO":"c","DT_MIPS_DELTA_SYM":"c","DT_MIPS_DELTA_SYM_NO":"c","DT_MIPS_DYNSTR_ALIGN":"c","DT_MIPS_FLAGS":"c","DT_MIPS_GOTSYM":"c","DT_MIPS_GP_VALUE":"c","DT_MIPS_HIDDEN_GOTIDX":"c","DT_MIPS_HIPAGENO":"c","DT_MIPS_ICHECKSUM":"c","DT_MIPS_INTERFACE":"c","DT_MIPS_INTERFACE_SIZE":"c","DT_MIPS_IVERSION":"c","DT_MIPS_LIBLIST":"c","DT_MIPS_LIBLISTNO":"c","DT_MIPS_LOCALPAGE_GOTIDX":"c","DT_MIPS_LOCAL_GOTIDX":"c","DT_MIPS_LOCAL_GOTNO":"c","DT_MIPS_MSYM":"c","DT_MIPS_OPTIONS":"c","DT_MIPS_PERF_SUFFIX":"c","DT_MIPS_PIXIE_INIT":"c","DT_MIPS_PLTGOT":"c","DT_MIPS_PROTECTED_GOTIDX":"c","DT_MIPS_RLD_MAP":"c","DT_MIPS_RLD_MAP_REL":"c","DT_MIPS_RLD_TEXT_RESOLVE_ADDR":"c","DT_MIPS_RLD_VERSION":"c","DT_MIPS_RWPLT":"c","DT_MIPS_SYMBOL_LIB":"c","DT_MIPS_SYMTABNO":"c","DT_MIPS_TIME_STAMP":"c","DT_MIPS_UNREFEXTNO":"c","DT_MOVEENT":"c","DT_MOVESZ":"c","DT_MOVETAB":"c","DT_NEEDED":"c","DT_NULL":"c","DT_PLTGOT":"c","DT_PLTPAD":"c","DT_PLTPADSZ":"c","DT_PLTREL":"c","DT_PLTRELSZ":"c","DT_POSFLAG_1":"c","DT_PPC64_GLINK":"c","DT_PPC64_OPD":"c","DT_PPC64_OPDSZ":"c","DT_PPC64_OPT":"c","DT_PPC_GOT":"c","DT_PPC_OPT":"c","DT_PREINIT_ARRAY":"c","DT_PREINIT_ARRAYSZ":"c","DT_REL":"c","DT_RELA":"c","DT_RELACOUNT":"c","DT_RELAENT":"c","DT_RELASZ":"c","DT_RELCOUNT":"c","DT_RELENT":"c","DT_RELSZ":"c","DT_RPATH":"c","DT_RUNPATH":"c","DT_SONAME":"c","DT_SPARC_REGISTER":"c","DT_STRSZ":"c","DT_STRTAB":"c","DT_SYMBOLIC":"c","DT_SYMENT":"c","DT_SYMINENT":"c","DT_SYMINFO":"c","DT_SYMINSZ":"c","DT_SYMTAB":"c","DT_SYMTAB_SHNDX":"c","DT_TEXTREL":"c","DT_TLSDESC_GOT":"c","DT_TLSDESC_PLT":"c","DT_USED":"c","DT_VALRNGHI":"c","DT_VALRNGLO":"c","DT_VERDEF":"c","DT_VERDEFNUM":"c","DT_VERNEED":"c","DT_VERNEEDNUM":"c","DT_VERSYM":"c","Data":"t","Data.GoString":"m","Data.String":"m","Dyn32":"t","Dyn64":"t","DynFlag":"t","DynFlag.GoString":"m","DynFlag.String":"m","DynFlag1":"t","DynFlag1.GoString":"m","DynFlag1.String":"m","DynTag":"t","DynTag.GoString":"m","DynTag.String":"m","DynamicVersion":"t","DynamicVersionDep":"t","DynamicVersionFlag":"t","DynamicVersionNeed":"t","EI_ABIVERSION":"c","EI_CLASS":"c","EI_DATA":"c","EI_NIDENT":"c","EI_OSABI":"c","EI_PAD":"c","EI_VERSION":"c","ELFCLASS32":"c","ELFCLASS64":"c","ELFCLASSNONE":"c","ELFDATA2LSB":"c","ELFDATA2MSB":"c","ELFDATANONE":"c","ELFMAG":"c","ELFOSABI_86OPEN":"c","ELFOSABI_AIX":"c","ELFOSABI_ARM":"c","ELFOSABI_AROS":"c","ELFOSABI_CLOUDABI":"c","ELFOSABI_FENIXOS":"c","ELFOSABI_FREEBSD":"c","ELFOSABI_HPUX":"c","ELFOSABI_HURD":"c","ELFOSABI_IRIX":"c","ELFOSABI_LINUX":"c","ELFOSABI_MODESTO":"c","ELFOSABI_NETBSD":"c","ELFOSABI_NONE":"c","ELFOSABI_NSK":"c","ELFOSABI_OPENBSD":"c","ELFOSABI_OPENVMS":"c","ELFOSABI_SOLARIS":"c","ELFOSABI_STANDALONE":"c","ELFOSABI_TRU64":"c","EM_386":"c","EM_486":"c","EM_56800EX":"c","EM_68HC05":"c","EM_68HC08":"c","EM_68HC11":"c","EM_68HC12":"c","EM_68HC16":"c","EM_68K":"c","EM_78KOR":"c","EM_8051":"c","EM_860":"c","EM_88K":"c","EM_960":"c","EM_AARCH64":"c","EM_ALPHA":"c","EM_ALPHA_STD":"c","EM_ALTERA_NIOS2":"c","EM_AMDGPU":"c","EM_ARC":"c","EM_ARCA":"c","EM_ARC_COMPACT":"c","EM_ARC_COMPACT2":"c","EM_ARM":"c","EM_AVR":"c","EM_AVR32":"c","EM_BA1":"c","EM_BA2":"c","EM_BLACKFIN":"c","EM_BPF":"c","EM_C166":"c","EM_CDP":"c","EM_CE":"c","EM_CLOUDSHIELD":"c","EM_COGE":"c","EM_COLDFIRE":"c","EM_COOL":"c","EM_COREA_1ST":"c","EM_COREA_2ND":"c","EM_CR":"c","EM_CR16":"c","EM_CRAYNV2":"c","EM_CRIS":"c","EM_CRX":"c","EM_CSR_KALIMBA":"c","EM_CUDA":"c","EM_CYPRESS_M8C":"c","EM_D10V":"c","EM_D30V":"c","EM_DSP24":"c","EM_DSPIC30F":"c","EM_DXP":"c","EM_ECOG1":"c","EM_ECOG16":"c","EM_ECOG1X":"c","EM_ECOG2":"c","EM_ETPU":"c","EM_EXCESS":"c","EM_F2MC16":"c","EM_FIREPATH":"c","EM_FR20":"c","EM_FR30":"c","EM_FT32":"c","EM_FX66":"c","EM_H8S":"c","EM_H8_300":"c","EM_H8_300H":"c","EM_H8_500":"c","EM_HUANY":"c","EM_IA_64":"c","EM_INTEL205":"c","EM_INTEL206":"c","EM_INTEL207":"c","EM_INTEL208":"c","EM_INTEL209":"c","EM_IP2K":"c","EM_JAVELIN":"c","EM_K10M":"c","EM_KM32":"c","EM_KMX16":"c","EM_KMX32":"c","EM_KMX8":"c","EM_KVARC":"c","EM_L10M":"c","EM_LANAI":"c","EM_LATTICEMICO32":"c","EM_LOONGARCH":"c","EM_M16C":"c","EM_M32":"c","EM_M32C":"c","EM_M32R":"c","EM_MANIK":"c","EM_MAX":"c","EM_MAXQ30":"c","EM_MCHP_PIC":"c","EM_MCST_ELBRUS":"c","EM_ME16":"c","EM_METAG":"c","EM_MICROBLAZE":"c","EM_MIPS":"c","EM_MIPS_RS3_LE":"c","EM_MIPS_RS4_BE":"c","EM_MIPS_X":"c","EM_MMA":"c","EM_MMDSP_PLUS":"c","EM_MMIX":"c","EM_MN10200":"c","EM_MN10300":"c","EM_MOXIE":"c","EM_MSP430":"c","EM_NCPU":"c","EM_NDR1":"c","EM_NDS32":"c","EM_NONE":"c","EM_NORC":"c","EM_NS32K":"c","EM_OPEN8":"c","EM_OPENRISC":"c","EM_PARISC":"c","EM_PCP":"c","EM_PDP10":"c","EM_PDP11":"c","EM_PDSP":"c","EM_PJ":"c","EM_PPC":"c","EM_PPC64":"c","EM_PRISM":"c","EM_QDSP6":"c","EM_R32C":"c","EM_RCE":"c","EM_RH32":"c","EM_RISCV":"c","EM_RL78":"c","EM_RS08":"c","EM_RX":"c","EM_S370":"c","EM_S390":"c","EM_SCORE7":"c","EM_SEP":"c","EM_SE_C17":"c","EM_SE_C33":"c","EM_SH":"c","EM_SHARC":"c","EM_SLE9X":"c","EM_SNP1K":"c","EM_SPARC":"c","EM_SPARC32PLUS":"c","EM_SPARCV9":"c","EM_ST100":"c","EM_ST19":"c","EM_ST200":"c","EM_ST7":"c","EM_ST9PLUS":"c","EM_STARCORE":"c","EM_STM8":"c","EM_STXP7X":"c","EM_SVX":"c","EM_TILE64":"c","EM_TILEGX":"c","EM_TILEPRO":"c","EM_TINYJ":"c","EM_TI_ARP32":"c","EM_TI_C2000":"c","EM_TI_C5500":"c","EM_TI_C6000":"c","EM_TI_PRU":"c","EM_TMM_GPP":"c","EM_TPC":"c","EM_TRICORE":"c","EM_TRIMEDIA":"c","EM_TSK3000":"c","EM_UNICORE":"c","EM_V800":"c","EM_V850":"c","EM_VAX":"c","EM_VIDEOCORE":"c","EM_VIDEOCORE3":"c","EM_VIDEOCORE5":"c","EM_VISIUM":"c","EM_VPP500":"c","EM_X86_64":"c","EM_XCORE":"c","EM_XGATE":"c","EM_XIMO16":"c","EM_XTENSA":"c","EM_Z80":"c","EM_ZSP":"c","ET_CORE":"c","ET_DYN":"c","ET_EXEC":"c","ET_HIOS":"c","ET_HIPROC":"c","ET_LOOS":"c","ET_LOPROC":"c","ET_NONE":"c","ET_REL":"c","EV_CURRENT":"c","EV_NONE":"c","ErrNoSymbols":"v","File":"t","File.Close":"m","File.DWARF":"m","File.DynString":"m","File.DynValue":"m","File.DynamicSymbols":"m","File.DynamicVersionNeeds":"m","File.DynamicVersions":"m","File.ImportedLibraries":"m","File.ImportedSymbols":"m","File.Section":"m","File.SectionByType":"m","File.Symbols":"m","FileHeader":"t","FormatError":"t","FormatError.Error":"m","Header32":"t","Header64":"t","ImportedSymbol":"t","Machine":"t","Machine.GoString":"m","Machine.String":"m","NT_FPREGSET":"c","NT_PRPSINFO":"c","NT_PRSTATUS":"c","NType":"t","NType.GoString":"m","NType.String":"m","NewFile":"f","OSABI":"t","OSABI.GoString":"m","OSABI.String":"m","Open":"f","PF_MASKOS":"c","PF_MASKPROC":"c","PF_R":"c","PF_W":"c","PF_X":"c","PT_AARCH64_ARCHEXT":"c","PT_AARCH64_UNWIND":"c","PT_ARM_ARCHEXT":"c","PT_ARM_EXIDX":"c","PT_DYNAMIC":"c","PT_GNU_EH_FRAME":"c","PT_GNU_MBIND_HI":"c","PT_GNU_MBIND_LO":"c","PT_GNU_PROPERTY":"c","PT_GNU_RELRO":"c","PT_GNU_STACK":"c","PT_HIOS":"c","PT_HIPROC":"c","PT_INTERP":"c","PT_LOAD":"c","PT_LOOS":"c","PT_LOPROC":"c","PT_MIPS_ABIFLAGS":"c","PT_MIPS_OPTIONS":"c","PT_MIPS_REGINFO":"c","PT_MIPS_RTPROC":"c","PT_NOTE":"c","PT_NULL":"c","PT_OPENBSD_BOOTDATA":"c","PT_OPENBSD_NOBTCFI":"c","PT_OPENBSD_RANDOMIZE":"c","PT_OPENBSD_WXNEEDED":"c","PT_PAX_FLAGS":"c","PT_PHDR":"c","PT_RISCV_ATTRIBUTES":"c","PT_S390_PGSTE":"c","PT_SHLIB":"c","PT_SUNWSTACK":"c","PT_SUNW_EH_FRAME":"c","PT_TLS":"c","Prog":"t","Prog.Open":"m","Prog32":"t","Prog64":"t","ProgFlag":"t","ProgFlag.GoString":"m","ProgFlag.String":"m","ProgHeader":"t","ProgType":"t","ProgType.GoString":"m","ProgType.String":"m","R_386":"t","R_386.GoString":"m","R_386.String":"m","R_386_16":"c","R_386_32":"c","R_386_32PLT":"c","R_386_8":"c","R_386_COPY":"c","R_386_GLOB_DAT":"c","R_386_GOT32":"c","R_386_GOT32X":"c","R_386_GOTOFF":"c","R_386_GOTPC":"c","R_386_IRELATIVE":"c","R_386_JMP_SLOT":"c","R_386_NONE":"c","R_386_PC16":"c","R_386_PC32":"c","R_386_PC8":"c","R_386_PLT32":"c","R_386_RELATIVE":"c","R_386_SIZE32":"c","R_386_TLS_DESC":"c","R_386_TLS_DESC_CALL":"c","R_386_TLS_DTPMOD32":"c","R_386_TLS_DTPOFF32":"c","R_386_TLS_GD":"c","R_386_TLS_GD_32":"c","R_386_TLS_GD_CALL":"c","R_386_TLS_GD_POP":"c","R_386_TLS_GD_PUSH":"c","R_386_TLS_GOTDESC":"c","R_386_TLS_GOTIE":"c","R_386_TLS_IE":"c","R_386_TLS_IE_32":"c","R_386_TLS_LDM":"c","R_386_TLS_LDM_32":"c","R_386_TLS_LDM_CALL":"c","R_386_TLS_LDM_POP":"c","R_386_TLS_LDM_PUSH":"c","R_386_TLS_LDO_32":"c","R_386_TLS_LE":"c","R_386_TLS_LE_32":"c","R_386_TLS_TPOFF":"c","R_386_TLS_TPOFF32":"c","R_390":"t","R_390.GoString":"m","R_390.String":"m","R_390_12":"c","R_390_16":"c","R_390_20":"c","R_390_32":"c","R_390_64":"c","R_390_8":"c","R_390_COPY":"c","R_390_GLOB_DAT":"c","R_390_GOT12":"c","R_390_GOT16":"c","R_390_GOT20":"c","R_390_GOT32":"c","R_390_GOT64":"c","R_390_GOTENT":"c","R_390_GOTOFF":"c","R_390_GOTOFF16":"c","R_390_GOTOFF64":"c","R_390_GOTPC":"c","R_390_GOTPCDBL":"c","R_390_GOTPLT12":"c","R_390_GOTPLT16":"c","R_390_GOTPLT20":"c","R_390_GOTPLT32":"c","R_390_GOTPLT64":"c","R_390_GOTPLTENT":"c","R_390_GOTPLTOFF16":"c","R_390_GOTPLTOFF32":"c","R_390_GOTPLTOFF64":"c","R_390_JMP_SLOT":"c","R_390_NONE":"c","R_390_PC16":"c","R_390_PC16DBL":"c","R_390_PC32":"c","R_390_PC32DBL":"c","R_390_PC64":"c","R_390_PLT16DBL":"c","R_390_PLT32":"c","R_390_PLT32DBL":"c","R_390_PLT64":"c","R_390_RELATIVE":"c","R_390_TLS_DTPMOD":"c","R_390_TLS_DTPOFF":"c","R_390_TLS_GD32":"c","R_390_TLS_GD64":"c","R_390_TLS_GDCALL":"c","R_390_TLS_GOTIE12":"c","R_390_TLS_GOTIE20":"c","R_390_TLS_GOTIE32":"c","R_390_TLS_GOTIE64":"c","R_390_TLS_IE32":"c","R_390_TLS_IE64":"c","R_390_TLS_IEENT":"c","R_390_TLS_LDCALL":"c","R_390_TLS_LDM32":"c","R_390_TLS_LDM64":"c","R_390_TLS_LDO32":"c","R_390_TLS_LDO64":"c","R_390_TLS_LE32":"c","R_390_TLS_LE64":"c","R_390_TLS_LOAD":"c","R_390_TLS_TPOFF":"c","R_AARCH64":"t","R_AARCH64.GoString":"m","R_AARCH64.String":"m","R_AARCH64_ABS16":"c","R_AARCH64_ABS32":"c","R_AARCH64_ABS64":"c","R_AARCH64_ADD_ABS_LO12_NC":"c","R_AARCH64_ADR_GOT_PAGE":"c","R_AARCH64_ADR_PREL_LO21":"c","R_AARCH64_ADR_PREL_PG_HI21":"c","R_AARCH64_ADR_PREL_PG_HI21_NC":"c","R_AARCH64_CALL26":"c","R_AARCH64_CONDBR19":"c","R_AARCH64_COPY":"c","R_AARCH64_GLOB_DAT":"c","R_AARCH64_GOT_LD_PREL19":"c","R_AARCH64_IRELATIVE":"c","R_AARCH64_JUMP26":"c","R_AARCH64_JUMP_SLOT":"c","R_AARCH64_LD64_GOTOFF_LO15":"c","R_AARCH64_LD64_GOTPAGE_LO15":"c","R_AARCH64_LD64_GOT_LO12_NC":"c","R_AARCH64_LDST128_ABS_LO12_NC":"c","R_AARCH64_LDST16_ABS_LO12_NC":"c","R_AARCH64_LDST32_ABS_LO12_NC":"c","R_AARCH64_LDST64_ABS_LO12_NC":"c","R_AARCH64_LDST8_ABS_LO12_NC":"c","R_AARCH64_LD_PREL_LO19":"c","R_AARCH64_MOVW_SABS_G0":"c","R_AARCH64_MOVW_SABS_G1":"c","R_AARCH64_MOVW_SABS_G2":"c","R_AARCH64_MOVW_UABS_G0":"c","R_AARCH64_MOVW_UABS_G0_NC":"c","R_AARCH64_MOVW_UABS_G1":"c","R_AARCH64_MOVW_UABS_G1_NC":"c","R_AARCH64_MOVW_UABS_G2":"c","R_AARCH64_MOVW_UABS_G2_NC":"c","R_AARCH64_MOVW_UABS_G3":"c","R_AARCH64_NONE":"c","R_AARCH64_NULL":"c","R_AARCH64_P32_ABS16":"c","R_AARCH64_P32_ABS32":"c","R_AARCH64_P32_ADD_ABS_LO12_NC":"c","R_AARCH64_P32_ADR_GOT_PAGE":"c","R_AARCH64_P32_ADR_PREL_LO21":"c","R_AARCH64_P32_ADR_PREL_PG_HI21":"c","R_AARCH64_P32_CALL26":"c","R_AARCH64_P32_CONDBR19":"c","R_AARCH64_P32_COPY":"c","R_AARCH64_P32_GLOB_DAT":"c","R_AARCH64_P32_GOT_LD_PREL19":"c","R_AARCH64_P32_IRELATIVE":"c","R_AARCH64_P32_JUMP26":"c","R_AARCH64_P32_JUMP_SLOT":"c","R_AARCH64_P32_LD32_GOT_LO12_NC":"c","R_AARCH64_P32_LDST128_ABS_LO12_NC":"c","R_AARCH64_P32_LDST16_ABS_LO12_NC":"c","R_AARCH64_P32_LDST32_ABS_LO12_NC":"c","R_AARCH64_P32_LDST64_ABS_LO12_NC":"c","R_AARCH64_P32_LDST8_ABS_LO12_NC":"c","R_AARCH64_P32_LD_PREL_LO19":"c","R_AARCH64_P32_MOVW_SABS_G0":"c","R_AARCH64_P32_MOVW_UABS_G0":"c","R_AARCH64_P32_MOVW_UABS_G0_NC":"c","R_AARCH64_P32_MOVW_UABS_G1":"c","R_AARCH64_P32_PREL16":"c","R_AARCH64_P32_PREL32":"c","R_AARCH64_P32_RELATIVE":"c","R_AARCH64_P32_TLSDESC":"c","R_AARCH64_P32_TLSDESC_ADD_LO12_NC":"c","R_AARCH64_P32_TLSDESC_ADR_PAGE21":"c","R_AARCH64_P32_TLSDESC_ADR_PREL21":"c","R_AARCH64_P32_TLSDESC_CALL":"c","R_AARCH64_P32_TLSDESC_LD32_LO12_NC":"c","R_AARCH64_P32_TLSDESC_LD_PREL19":"c","R_AARCH64_P32_TLSGD_ADD_LO12_NC":"c","R_AARCH64_P32_TLSGD_ADR_PAGE21":"c","R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21":"c","R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC":"c","R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19":"c","R_AARCH64_P32_TLSLE_ADD_TPREL_HI12":"c","R_AARCH64_P32_TLSLE_ADD_TPREL_LO12":"c","R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC":"c","R_AARCH64_P32_TLSLE_MOVW_TPREL_G0":"c","R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC":"c","R_AARCH64_P32_TLSLE_MOVW_TPREL_G1":"c","R_AARCH64_P32_TLS_DTPMOD":"c","R_AARCH64_P32_TLS_DTPREL":"c","R_AARCH64_P32_TLS_TPREL":"c","R_AARCH64_P32_TSTBR14":"c","R_AARCH64_PREL16":"c","R_AARCH64_PREL32":"c","R_AARCH64_PREL64":"c","R_AARCH64_RELATIVE":"c","R_AARCH64_TLSDESC":"c","R_AARCH64_TLSDESC_ADD":"c","R_AARCH64_TLSDESC_ADD_LO12_NC":"c","R_AARCH64_TLSDESC_ADR_PAGE21":"c","R_AARCH64_TLSDESC_ADR_PREL21":"c","R_AARCH64_TLSDESC_CALL":"c","R_AARCH64_TLSDESC_LD64_LO12_NC":"c","R_AARCH64_TLSDESC_LDR":"c","R_AARCH64_TLSDESC_LD_PREL19":"c","R_AARCH64_TLSDESC_OFF_G0_NC":"c","R_AARCH64_TLSDESC_OFF_G1":"c","R_AARCH64_TLSGD_ADD_LO12_NC":"c","R_AARCH64_TLSGD_ADR_PAGE21":"c","R_AARCH64_TLSGD_ADR_PREL21":"c","R_AARCH64_TLSGD_MOVW_G0_NC":"c","R_AARCH64_TLSGD_MOVW_G1":"c","R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21":"c","R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC":"c","R_AARCH64_TLSIE_LD_GOTTPREL_PREL19":"c","R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC":"c","R_AARCH64_TLSIE_MOVW_GOTTPREL_G1":"c","R_AARCH64_TLSLD_ADR_PAGE21":"c","R_AARCH64_TLSLD_ADR_PREL21":"c","R_AARCH64_TLSLD_LDST128_DTPREL_LO12":"c","R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC":"c","R_AARCH64_TLSLE_ADD_TPREL_HI12":"c","R_AARCH64_TLSLE_ADD_TPREL_LO12":"c","R_AARCH64_TLSLE_ADD_TPREL_LO12_NC":"c","R_AARCH64_TLSLE_LDST128_TPREL_LO12":"c","R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC":"c","R_AARCH64_TLSLE_MOVW_TPREL_G0":"c","R_AARCH64_TLSLE_MOVW_TPREL_G0_NC":"c","R_AARCH64_TLSLE_MOVW_TPREL_G1":"c","R_AARCH64_TLSLE_MOVW_TPREL_G1_NC":"c","R_AARCH64_TLSLE_MOVW_TPREL_G2":"c","R_AARCH64_TLS_DTPMOD64":"c","R_AARCH64_TLS_DTPREL64":"c","R_AARCH64_TLS_TPREL64":"c","R_AARCH64_TSTBR14":"c","R_ALPHA":"t","R_ALPHA.GoString":"m","R_ALPHA.String":"m","R_ALPHA_BRADDR":"c","R_ALPHA_COPY":"c","R_ALPHA_GLOB_DAT":"c","R_ALPHA_GPDISP":"c","R_ALPHA_GPREL32":"c","R_ALPHA_GPRELHIGH":"c","R_ALPHA_GPRELLOW":"c","R_ALPHA_GPVALUE":"c","R_ALPHA_HINT":"c","R_ALPHA_IMMED_BR_HI32":"c","R_ALPHA_IMMED_GP_16":"c","R_ALPHA_IMMED_GP_HI32":"c","R_ALPHA_IMMED_LO32":"c","R_ALPHA_IMMED_SCN_HI32":"c","R_ALPHA_JMP_SLOT":"c","R_ALPHA_LITERAL":"c","R_ALPHA_LITUSE":"c","R_ALPHA_NONE":"c","R_ALPHA_OP_PRSHIFT":"c","R_ALPHA_OP_PSUB":"c","R_ALPHA_OP_PUSH":"c","R_ALPHA_OP_STORE":"c","R_ALPHA_REFLONG":"c","R_ALPHA_REFQUAD":"c","R_ALPHA_RELATIVE":"c","R_ALPHA_SREL16":"c","R_ALPHA_SREL32":"c","R_ALPHA_SREL64":"c","R_ARM":"t","R_ARM.GoString":"m","R_ARM.String":"m","R_ARM_ABS12":"c","R_ARM_ABS16":"c","R_ARM_ABS32":"c","R_ARM_ABS32_NOI":"c","R_ARM_ABS8":"c","R_ARM_ALU_PCREL_15_8":"c","R_ARM_ALU_PCREL_23_15":"c","R_ARM_ALU_PCREL_7_0":"c","R_ARM_ALU_PC_G0":"c","R_ARM_ALU_PC_G0_NC":"c","R_ARM_ALU_PC_G1":"c","R_ARM_ALU_PC_G1_NC":"c","R_ARM_ALU_PC_G2":"c","R_ARM_ALU_SBREL_19_12_NC":"c","R_ARM_ALU_SBREL_27_20_CK":"c","R_ARM_ALU_SB_G0":"c","R_ARM_ALU_SB_G0_NC":"c","R_ARM_ALU_SB_G1":"c","R_ARM_ALU_SB_G1_NC":"c","R_ARM_ALU_SB_G2":"c","R_ARM_AMP_VCALL9":"c","R_ARM_BASE_ABS":"c","R_ARM_CALL":"c","R_ARM_COPY":"c","R_ARM_GLOB_DAT":"c","R_ARM_GNU_VTENTRY":"c","R_ARM_GNU_VTINHERIT":"c","R_ARM_GOT32":"c","R_ARM_GOTOFF":"c","R_ARM_GOTOFF12":"c","R_ARM_GOTPC":"c","R_ARM_GOTRELAX":"c","R_ARM_GOT_ABS":"c","R_ARM_GOT_BREL12":"c","R_ARM_GOT_PREL":"c","R_ARM_IRELATIVE":"c","R_ARM_JUMP24":"c","R_ARM_JUMP_SLOT":"c","R_ARM_LDC_PC_G0":"c","R_ARM_LDC_PC_G1":"c","R_ARM_LDC_PC_G2":"c","R_ARM_LDC_SB_G0":"c","R_ARM_LDC_SB_G1":"c","R_ARM_LDC_SB_G2":"c","R_ARM_LDRS_PC_G0":"c","R_ARM_LDRS_PC_G1":"c","R_ARM_LDRS_PC_G2":"c","R_ARM_LDRS_SB_G0":"c","R_ARM_LDRS_SB_G1":"c","R_ARM_LDRS_SB_G2":"c","R_ARM_LDR_PC_G1":"c","R_ARM_LDR_PC_G2":"c","R_ARM_LDR_SBREL_11_10_NC":"c","R_ARM_LDR_SB_G0":"c","R_ARM_LDR_SB_G1":"c","R_ARM_LDR_SB_G2":"c","R_ARM_ME_TOO":"c","R_ARM_MOVT_ABS":"c","R_ARM_MOVT_BREL":"c","R_ARM_MOVT_PREL":"c","R_ARM_MOVW_ABS_NC":"c","R_ARM_MOVW_BREL":"c","R_ARM_MOVW_BREL_NC":"c","R_ARM_MOVW_PREL_NC":"c","R_ARM_NONE":"c","R_ARM_PC13":"c","R_ARM_PC24":"c","R_ARM_PLT32":"c","R_ARM_PLT32_ABS":"c","R_ARM_PREL31":"c","R_ARM_PRIVATE_0":"c","R_ARM_PRIVATE_1":"c","R_ARM_PRIVATE_10":"c","R_ARM_PRIVATE_11":"c","R_ARM_PRIVATE_12":"c","R_ARM_PRIVATE_13":"c","R_ARM_PRIVATE_14":"c","R_ARM_PRIVATE_15":"c","R_ARM_PRIVATE_2":"c","R_ARM_PRIVATE_3":"c","R_ARM_PRIVATE_4":"c","R_ARM_PRIVATE_5":"c","R_ARM_PRIVATE_6":"c","R_ARM_PRIVATE_7":"c","R_ARM_PRIVATE_8":"c","R_ARM_PRIVATE_9":"c","R_ARM_RABS32":"c","R_ARM_RBASE":"c","R_ARM_REL32":"c","R_ARM_REL32_NOI":"c","R_ARM_RELATIVE":"c","R_ARM_RPC24":"c","R_ARM_RREL32":"c","R_ARM_RSBREL32":"c","R_ARM_RXPC25":"c","R_ARM_SBREL31":"c","R_ARM_SBREL32":"c","R_ARM_SWI24":"c","R_ARM_TARGET1":"c","R_ARM_TARGET2":"c","R_ARM_THM_ABS5":"c","R_ARM_THM_ALU_ABS_G0_NC":"c","R_ARM_THM_ALU_ABS_G1_NC":"c","R_ARM_THM_ALU_ABS_G2_NC":"c","R_ARM_THM_ALU_ABS_G3":"c","R_ARM_THM_ALU_PREL_11_0":"c","R_ARM_THM_GOT_BREL12":"c","R_ARM_THM_JUMP11":"c","R_ARM_THM_JUMP19":"c","R_ARM_THM_JUMP24":"c","R_ARM_THM_JUMP6":"c","R_ARM_THM_JUMP8":"c","R_ARM_THM_MOVT_ABS":"c","R_ARM_THM_MOVT_BREL":"c","R_ARM_THM_MOVT_PREL":"c","R_ARM_THM_MOVW_ABS_NC":"c","R_ARM_THM_MOVW_BREL":"c","R_ARM_THM_MOVW_BREL_NC":"c","R_ARM_THM_MOVW_PREL_NC":"c","R_ARM_THM_PC12":"c","R_ARM_THM_PC22":"c","R_ARM_THM_PC8":"c","R_ARM_THM_RPC22":"c","R_ARM_THM_SWI8":"c","R_ARM_THM_TLS_CALL":"c","R_ARM_THM_TLS_DESCSEQ16":"c","R_ARM_THM_TLS_DESCSEQ32":"c","R_ARM_THM_XPC22":"c","R_ARM_TLS_CALL":"c","R_ARM_TLS_DESCSEQ":"c","R_ARM_TLS_DTPMOD32":"c","R_ARM_TLS_DTPOFF32":"c","R_ARM_TLS_GD32":"c","R_ARM_TLS_GOTDESC":"c","R_ARM_TLS_IE12GP":"c","R_ARM_TLS_IE32":"c","R_ARM_TLS_LDM32":"c","R_ARM_TLS_LDO12":"c","R_ARM_TLS_LDO32":"c","R_ARM_TLS_LE12":"c","R_ARM_TLS_LE32":"c","R_ARM_TLS_TPOFF32":"c","R_ARM_V4BX":"c","R_ARM_XPC25":"c","R_INFO":"f","R_INFO32":"f","R_LARCH":"t","R_LARCH.GoString":"m","R_LARCH.String":"m","R_LARCH_32":"c","R_LARCH_32_PCREL":"c","R_LARCH_64":"c","R_LARCH_64_PCREL":"c","R_LARCH_ABS64_HI12":"c","R_LARCH_ABS64_LO20":"c","R_LARCH_ABS_HI20":"c","R_LARCH_ABS_LO12":"c","R_LARCH_ADD16":"c","R_LARCH_ADD24":"c","R_LARCH_ADD32":"c","R_LARCH_ADD6":"c","R_LARCH_ADD64":"c","R_LARCH_ADD8":"c","R_LARCH_ADD_ULEB128":"c","R_LARCH_ALIGN":"c","R_LARCH_B16":"c","R_LARCH_B21":"c","R_LARCH_B26":"c","R_LARCH_CFA":"c","R_LARCH_COPY":"c","R_LARCH_DELETE":"c","R_LARCH_GNU_VTENTRY":"c","R_LARCH_GNU_VTINHERIT":"c","R_LARCH_GOT64_HI12":"c","R_LARCH_GOT64_LO20":"c","R_LARCH_GOT64_PC_HI12":"c","R_LARCH_GOT64_PC_LO20":"c","R_LARCH_GOT_HI20":"c","R_LARCH_GOT_LO12":"c","R_LARCH_GOT_PC_HI20":"c","R_LARCH_GOT_PC_LO12":"c","R_LARCH_IRELATIVE":"c","R_LARCH_JUMP_SLOT":"c","R_LARCH_MARK_LA":"c","R_LARCH_MARK_PCREL":"c","R_LARCH_NONE":"c","R_LARCH_PCALA64_HI12":"c","R_LARCH_PCALA64_LO20":"c","R_LARCH_PCALA_HI20":"c","R_LARCH_PCALA_LO12":"c","R_LARCH_PCREL20_S2":"c","R_LARCH_RELATIVE":"c","R_LARCH_RELAX":"c","R_LARCH_SOP_ADD":"c","R_LARCH_SOP_AND":"c","R_LARCH_SOP_ASSERT":"c","R_LARCH_SOP_IF_ELSE":"c","R_LARCH_SOP_NOT":"c","R_LARCH_SOP_POP_32_S_0_10_10_16_S2":"c","R_LARCH_SOP_POP_32_S_0_5_10_16_S2":"c","R_LARCH_SOP_POP_32_S_10_12":"c","R_LARCH_SOP_POP_32_S_10_16":"c","R_LARCH_SOP_POP_32_S_10_16_S2":"c","R_LARCH_SOP_POP_32_S_10_5":"c","R_LARCH_SOP_POP_32_S_5_20":"c","R_LARCH_SOP_POP_32_U":"c","R_LARCH_SOP_POP_32_U_10_12":"c","R_LARCH_SOP_PUSH_ABSOLUTE":"c","R_LARCH_SOP_PUSH_DUP":"c","R_LARCH_SOP_PUSH_GPREL":"c","R_LARCH_SOP_PUSH_PCREL":"c","R_LARCH_SOP_PUSH_PLT_PCREL":"c","R_LARCH_SOP_PUSH_TLS_GD":"c","R_LARCH_SOP_PUSH_TLS_GOT":"c","R_LARCH_SOP_PUSH_TLS_TPREL":"c","R_LARCH_SOP_SL":"c","R_LARCH_SOP_SR":"c","R_LARCH_SOP_SUB":"c","R_LARCH_SUB16":"c","R_LARCH_SUB24":"c","R_LARCH_SUB32":"c","R_LARCH_SUB6":"c","R_LARCH_SUB64":"c","R_LARCH_SUB8":"c","R_LARCH_SUB_ULEB128":"c","R_LARCH_TLS_DTPMOD32":"c","R_LARCH_TLS_DTPMOD64":"c","R_LARCH_TLS_DTPREL32":"c","R_LARCH_TLS_DTPREL64":"c","R_LARCH_TLS_GD_HI20":"c","R_LARCH_TLS_GD_PC_HI20":"c","R_LARCH_TLS_IE64_HI12":"c","R_LARCH_TLS_IE64_LO20":"c","R_LARCH_TLS_IE64_PC_HI12":"c","R_LARCH_TLS_IE64_PC_LO20":"c","R_LARCH_TLS_IE_HI20":"c","R_LARCH_TLS_IE_LO12":"c","R_LARCH_TLS_IE_PC_HI20":"c","R_LARCH_TLS_IE_PC_LO12":"c","R_LARCH_TLS_LD_HI20":"c","R_LARCH_TLS_LD_PC_HI20":"c","R_LARCH_TLS_LE64_HI12":"c","R_LARCH_TLS_LE64_LO20":"c","R_LARCH_TLS_LE_HI20":"c","R_LARCH_TLS_LE_LO12":"c","R_LARCH_TLS_TPREL32":"c","R_LARCH_TLS_TPREL64":"c","R_MIPS":"t","R_MIPS.GoString":"m","R_MIPS.String":"m","R_MIPS_16":"c","R_MIPS_26":"c","R_MIPS_32":"c","R_MIPS_64":"c","R_MIPS_ADD_IMMEDIATE":"c","R_MIPS_CALL16":"c","R_MIPS_CALL_HI16":"c","R_MIPS_CALL_LO16":"c","R_MIPS_DELETE":"c","R_MIPS_GOT16":"c","R_MIPS_GOT_DISP":"c","R_MIPS_GOT_HI16":"c","R_MIPS_GOT_LO16":"c","R_MIPS_GOT_OFST":"c","R_MIPS_GOT_PAGE":"c","R_MIPS_GPREL16":"c","R_MIPS_GPREL32":"c","R_MIPS_HI16":"c","R_MIPS_HIGHER":"c","R_MIPS_HIGHEST":"c","R_MIPS_INSERT_A":"c","R_MIPS_INSERT_B":"c","R_MIPS_JALR":"c","R_MIPS_LITERAL":"c","R_MIPS_LO16":"c","R_MIPS_NONE":"c","R_MIPS_PC16":"c","R_MIPS_PC32":"c","R_MIPS_PJUMP":"c","R_MIPS_REL16":"c","R_MIPS_REL32":"c","R_MIPS_RELGOT":"c","R_MIPS_SCN_DISP":"c","R_MIPS_SHIFT5":"c","R_MIPS_SHIFT6":"c","R_MIPS_SUB":"c","R_MIPS_TLS_DTPMOD32":"c","R_MIPS_TLS_DTPMOD64":"c","R_MIPS_TLS_DTPREL32":"c","R_MIPS_TLS_DTPREL64":"c","R_MIPS_TLS_DTPREL_HI16":"c","R_MIPS_TLS_DTPREL_LO16":"c","R_MIPS_TLS_GD":"c","R_MIPS_TLS_GOTTPREL":"c","R_MIPS_TLS_LDM":"c","R_MIPS_TLS_TPREL32":"c","R_MIPS_TLS_TPREL64":"c","R_MIPS_TLS_TPREL_HI16":"c","R_MIPS_TLS_TPREL_LO16":"c","R_PPC":"t","R_PPC.GoString":"m","R_PPC.String":"m","R_PPC64":"t","R_PPC64.GoString":"m","R_PPC64.String":"m","R_PPC64_ADDR14":"c","R_PPC64_ADDR14_BRNTAKEN":"c","R_PPC64_ADDR14_BRTAKEN":"c","R_PPC64_ADDR16":"c","R_PPC64_ADDR16_DS":"c","R_PPC64_ADDR16_HA":"c","R_PPC64_ADDR16_HI":"c","R_PPC64_ADDR16_HIGH":"c","R_PPC64_ADDR16_HIGHA":"c","R_PPC64_ADDR16_HIGHER":"c","R_PPC64_ADDR16_HIGHER34":"c","R_PPC64_ADDR16_HIGHERA":"c","R_PPC64_ADDR16_HIGHERA34":"c","R_PPC64_ADDR16_HIGHEST":"c","R_PPC64_ADDR16_HIGHEST34":"c","R_PPC64_ADDR16_HIGHESTA":"c","R_PPC64_ADDR16_HIGHESTA34":"c","R_PPC64_ADDR16_LO":"c","R_PPC64_ADDR16_LO_DS":"c","R_PPC64_ADDR24":"c","R_PPC64_ADDR32":"c","R_PPC64_ADDR64":"c","R_PPC64_ADDR64_LOCAL":"c","R_PPC64_COPY":"c","R_PPC64_D28":"c","R_PPC64_D34":"c","R_PPC64_D34_HA30":"c","R_PPC64_D34_HI30":"c","R_PPC64_D34_LO":"c","R_PPC64_DTPMOD64":"c","R_PPC64_DTPREL16":"c","R_PPC64_DTPREL16_DS":"c","R_PPC64_DTPREL16_HA":"c","R_PPC64_DTPREL16_HI":"c","R_PPC64_DTPREL16_HIGH":"c","R_PPC64_DTPREL16_HIGHA":"c","R_PPC64_DTPREL16_HIGHER":"c","R_PPC64_DTPREL16_HIGHERA":"c","R_PPC64_DTPREL16_HIGHEST":"c","R_PPC64_DTPREL16_HIGHESTA":"c","R_PPC64_DTPREL16_LO":"c","R_PPC64_DTPREL16_LO_DS":"c","R_PPC64_DTPREL34":"c","R_PPC64_DTPREL64":"c","R_PPC64_ENTRY":"c","R_PPC64_GLOB_DAT":"c","R_PPC64_GNU_VTENTRY":"c","R_PPC64_GNU_VTINHERIT":"c","R_PPC64_GOT16":"c","R_PPC64_GOT16_DS":"c","R_PPC64_GOT16_HA":"c","R_PPC64_GOT16_HI":"c","R_PPC64_GOT16_LO":"c","R_PPC64_GOT16_LO_DS":"c","R_PPC64_GOT_DTPREL16_DS":"c","R_PPC64_GOT_DTPREL16_HA":"c","R_PPC64_GOT_DTPREL16_HI":"c","R_PPC64_GOT_DTPREL16_LO_DS":"c","R_PPC64_GOT_DTPREL_PCREL34":"c","R_PPC64_GOT_PCREL34":"c","R_PPC64_GOT_TLSGD16":"c","R_PPC64_GOT_TLSGD16_HA":"c","R_PPC64_GOT_TLSGD16_HI":"c","R_PPC64_GOT_TLSGD16_LO":"c","R_PPC64_GOT_TLSGD_PCREL34":"c","R_PPC64_GOT_TLSLD16":"c","R_PPC64_GOT_TLSLD16_HA":"c","R_PPC64_GOT_TLSLD16_HI":"c","R_PPC64_GOT_TLSLD16_LO":"c","R_PPC64_GOT_TLSLD_PCREL34":"c","R_PPC64_GOT_TPREL16_DS":"c","R_PPC64_GOT_TPREL16_HA":"c","R_PPC64_GOT_TPREL16_HI":"c","R_PPC64_GOT_TPREL16_LO_DS":"c","R_PPC64_GOT_TPREL_PCREL34":"c","R_PPC64_IRELATIVE":"c","R_PPC64_JMP_IREL":"c","R_PPC64_JMP_SLOT":"c","R_PPC64_NONE":"c","R_PPC64_PCREL28":"c","R_PPC64_PCREL34":"c","R_PPC64_PCREL_OPT":"c","R_PPC64_PLT16_HA":"c","R_PPC64_PLT16_HI":"c","R_PPC64_PLT16_LO":"c","R_PPC64_PLT16_LO_DS":"c","R_PPC64_PLT32":"c","R_PPC64_PLT64":"c","R_PPC64_PLTCALL":"c","R_PPC64_PLTCALL_NOTOC":"c","R_PPC64_PLTGOT16":"c","R_PPC64_PLTGOT16_DS":"c","R_PPC64_PLTGOT16_HA":"c","R_PPC64_PLTGOT16_HI":"c","R_PPC64_PLTGOT16_LO":"c","R_PPC64_PLTGOT_LO_DS":"c","R_PPC64_PLTREL32":"c","R_PPC64_PLTREL64":"c","R_PPC64_PLTSEQ":"c","R_PPC64_PLTSEQ_NOTOC":"c","R_PPC64_PLT_PCREL34":"c","R_PPC64_PLT_PCREL34_NOTOC":"c","R_PPC64_REL14":"c","R_PPC64_REL14_BRNTAKEN":"c","R_PPC64_REL14_BRTAKEN":"c","R_PPC64_REL16":"c","R_PPC64_REL16DX_HA":"c","R_PPC64_REL16_HA":"c","R_PPC64_REL16_HI":"c","R_PPC64_REL16_HIGH":"c","R_PPC64_REL16_HIGHA":"c","R_PPC64_REL16_HIGHER":"c","R_PPC64_REL16_HIGHER34":"c","R_PPC64_REL16_HIGHERA":"c","R_PPC64_REL16_HIGHERA34":"c","R_PPC64_REL16_HIGHEST":"c","R_PPC64_REL16_HIGHEST34":"c","R_PPC64_REL16_HIGHESTA":"c","R_PPC64_REL16_HIGHESTA34":"c","R_PPC64_REL16_LO":"c","R_PPC64_REL24":"c","R_PPC64_REL24_NOTOC":"c","R_PPC64_REL24_P9NOTOC":"c","R_PPC64_REL30":"c","R_PPC64_REL32":"c","R_PPC64_REL64":"c","R_PPC64_RELATIVE":"c","R_PPC64_SECTOFF":"c","R_PPC64_SECTOFF_DS":"c","R_PPC64_SECTOFF_HA":"c","R_PPC64_SECTOFF_HI":"c","R_PPC64_SECTOFF_LO":"c","R_PPC64_SECTOFF_LO_DS":"c","R_PPC64_TLS":"c","R_PPC64_TLSGD":"c","R_PPC64_TLSLD":"c","R_PPC64_TOC":"c","R_PPC64_TOC16":"c","R_PPC64_TOC16_DS":"c","R_PPC64_TOC16_HA":"c","R_PPC64_TOC16_HI":"c","R_PPC64_TOC16_LO":"c","R_PPC64_TOC16_LO_DS":"c","R_PPC64_TOCSAVE":"c","R_PPC64_TPREL16":"c","R_PPC64_TPREL16_DS":"c","R_PPC64_TPREL16_HA":"c","R_PPC64_TPREL16_HI":"c","R_PPC64_TPREL16_HIGH":"c","R_PPC64_TPREL16_HIGHA":"c","R_PPC64_TPREL16_HIGHER":"c","R_PPC64_TPREL16_HIGHERA":"c","R_PPC64_TPREL16_HIGHEST":"c","R_PPC64_TPREL16_HIGHESTA":"c","R_PPC64_TPREL16_LO":"c","R_PPC64_TPREL16_LO_DS":"c","R_PPC64_TPREL34":"c","R_PPC64_TPREL64":"c","R_PPC64_UADDR16":"c","R_PPC64_UADDR32":"c","R_PPC64_UADDR64":"c","R_PPC_ADDR14":"c","R_PPC_ADDR14_BRNTAKEN":"c","R_PPC_ADDR14_BRTAKEN":"c","R_PPC_ADDR16":"c","R_PPC_ADDR16_HA":"c","R_PPC_ADDR16_HI":"c","R_PPC_ADDR16_LO":"c","R_PPC_ADDR24":"c","R_PPC_ADDR32":"c","R_PPC_COPY":"c","R_PPC_DTPMOD32":"c","R_PPC_DTPREL16":"c","R_PPC_DTPREL16_HA":"c","R_PPC_DTPREL16_HI":"c","R_PPC_DTPREL16_LO":"c","R_PPC_DTPREL32":"c","R_PPC_EMB_BIT_FLD":"c","R_PPC_EMB_MRKREF":"c","R_PPC_EMB_NADDR16":"c","R_PPC_EMB_NADDR16_HA":"c","R_PPC_EMB_NADDR16_HI":"c","R_PPC_EMB_NADDR16_LO":"c","R_PPC_EMB_NADDR32":"c","R_PPC_EMB_RELSDA":"c","R_PPC_EMB_RELSEC16":"c","R_PPC_EMB_RELST_HA":"c","R_PPC_EMB_RELST_HI":"c","R_PPC_EMB_RELST_LO":"c","R_PPC_EMB_SDA21":"c","R_PPC_EMB_SDA2I16":"c","R_PPC_EMB_SDA2REL":"c","R_PPC_EMB_SDAI16":"c","R_PPC_GLOB_DAT":"c","R_PPC_GOT16":"c","R_PPC_GOT16_HA":"c","R_PPC_GOT16_HI":"c","R_PPC_GOT16_LO":"c","R_PPC_GOT_TLSGD16":"c","R_PPC_GOT_TLSGD16_HA":"c","R_PPC_GOT_TLSGD16_HI":"c","R_PPC_GOT_TLSGD16_LO":"c","R_PPC_GOT_TLSLD16":"c","R_PPC_GOT_TLSLD16_HA":"c","R_PPC_GOT_TLSLD16_HI":"c","R_PPC_GOT_TLSLD16_LO":"c","R_PPC_GOT_TPREL16":"c","R_PPC_GOT_TPREL16_HA":"c","R_PPC_GOT_TPREL16_HI":"c","R_PPC_GOT_TPREL16_LO":"c","R_PPC_JMP_SLOT":"c","R_PPC_LOCAL24PC":"c","R_PPC_NONE":"c","R_PPC_PLT16_HA":"c","R_PPC_PLT16_HI":"c","R_PPC_PLT16_LO":"c","R_PPC_PLT32":"c","R_PPC_PLTREL24":"c","R_PPC_PLTREL32":"c","R_PPC_REL14":"c","R_PPC_REL14_BRNTAKEN":"c","R_PPC_REL14_BRTAKEN":"c","R_PPC_REL24":"c","R_PPC_REL32":"c","R_PPC_RELATIVE":"c","R_PPC_SDAREL16":"c","R_PPC_SECTOFF":"c","R_PPC_SECTOFF_HA":"c","R_PPC_SECTOFF_HI":"c","R_PPC_SECTOFF_LO":"c","R_PPC_TLS":"c","R_PPC_TPREL16":"c","R_PPC_TPREL16_HA":"c","R_PPC_TPREL16_HI":"c","R_PPC_TPREL16_LO":"c","R_PPC_TPREL32":"c","R_PPC_UADDR16":"c","R_PPC_UADDR32":"c","R_RISCV":"t","R_RISCV.GoString":"m","R_RISCV.String":"m","R_RISCV_32":"c","R_RISCV_32_PCREL":"c","R_RISCV_64":"c","R_RISCV_ADD16":"c","R_RISCV_ADD32":"c","R_RISCV_ADD64":"c","R_RISCV_ADD8":"c","R_RISCV_ALIGN":"c","R_RISCV_BRANCH":"c","R_RISCV_CALL":"c","R_RISCV_CALL_PLT":"c","R_RISCV_COPY":"c","R_RISCV_GNU_VTENTRY":"c","R_RISCV_GNU_VTINHERIT":"c","R_RISCV_GOT_HI20":"c","R_RISCV_GPREL_I":"c","R_RISCV_GPREL_S":"c","R_RISCV_HI20":"c","R_RISCV_JAL":"c","R_RISCV_JUMP_SLOT":"c","R_RISCV_LO12_I":"c","R_RISCV_LO12_S":"c","R_RISCV_NONE":"c","R_RISCV_PCREL_HI20":"c","R_RISCV_PCREL_LO12_I":"c","R_RISCV_PCREL_LO12_S":"c","R_RISCV_RELATIVE":"c","R_RISCV_RELAX":"c","R_RISCV_RVC_BRANCH":"c","R_RISCV_RVC_JUMP":"c","R_RISCV_RVC_LUI":"c","R_RISCV_SET16":"c","R_RISCV_SET32":"c","R_RISCV_SET6":"c","R_RISCV_SET8":"c","R_RISCV_SUB16":"c","R_RISCV_SUB32":"c","R_RISCV_SUB6":"c","R_RISCV_SUB64":"c","R_RISCV_SUB8":"c","R_RISCV_TLS_DTPMOD32":"c","R_RISCV_TLS_DTPMOD64":"c","R_RISCV_TLS_DTPREL32":"c","R_RISCV_TLS_DTPREL64":"c","R_RISCV_TLS_GD_HI20":"c","R_RISCV_TLS_GOT_HI20":"c","R_RISCV_TLS_TPREL32":"c","R_RISCV_TLS_TPREL64":"c","R_RISCV_TPREL_ADD":"c","R_RISCV_TPREL_HI20":"c","R_RISCV_TPREL_I":"c","R_RISCV_TPREL_LO12_I":"c","R_RISCV_TPREL_LO12_S":"c","R_RISCV_TPREL_S":"c","R_SPARC":"t","R_SPARC.GoString":"m","R_SPARC.String":"m","R_SPARC_10":"c","R_SPARC_11":"c","R_SPARC_13":"c","R_SPARC_16":"c","R_SPARC_22":"c","R_SPARC_32":"c","R_SPARC_5":"c","R_SPARC_6":"c","R_SPARC_64":"c","R_SPARC_7":"c","R_SPARC_8":"c","R_SPARC_COPY":"c","R_SPARC_DISP16":"c","R_SPARC_DISP32":"c","R_SPARC_DISP64":"c","R_SPARC_DISP8":"c","R_SPARC_GLOB_DAT":"c","R_SPARC_GLOB_JMP":"c","R_SPARC_GOT10":"c","R_SPARC_GOT13":"c","R_SPARC_GOT22":"c","R_SPARC_H44":"c","R_SPARC_HH22":"c","R_SPARC_HI22":"c","R_SPARC_HIPLT22":"c","R_SPARC_HIX22":"c","R_SPARC_HM10":"c","R_SPARC_JMP_SLOT":"c","R_SPARC_L44":"c","R_SPARC_LM22":"c","R_SPARC_LO10":"c","R_SPARC_LOPLT10":"c","R_SPARC_LOX10":"c","R_SPARC_M44":"c","R_SPARC_NONE":"c","R_SPARC_OLO10":"c","R_SPARC_PC10":"c","R_SPARC_PC22":"c","R_SPARC_PCPLT10":"c","R_SPARC_PCPLT22":"c","R_SPARC_PCPLT32":"c","R_SPARC_PC_HH22":"c","R_SPARC_PC_HM10":"c","R_SPARC_PC_LM22":"c","R_SPARC_PLT32":"c","R_SPARC_PLT64":"c","R_SPARC_REGISTER":"c","R_SPARC_RELATIVE":"c","R_SPARC_UA16":"c","R_SPARC_UA32":"c","R_SPARC_UA64":"c","R_SPARC_WDISP16":"c","R_SPARC_WDISP19":"c","R_SPARC_WDISP22":"c","R_SPARC_WDISP30":"c","R_SPARC_WPLT30":"c","R_SYM32":"f","R_SYM64":"f","R_TYPE32":"f","R_TYPE64":"f","R_X86_64":"t","R_X86_64.GoString":"m","R_X86_64.String":"m","R_X86_64_16":"c","R_X86_64_32":"c","R_X86_64_32S":"c","R_X86_64_64":"c","R_X86_64_8":"c","R_X86_64_COPY":"c","R_X86_64_DTPMOD64":"c","R_X86_64_DTPOFF32":"c","R_X86_64_DTPOFF64":"c","R_X86_64_GLOB_DAT":"c","R_X86_64_GOT32":"c","R_X86_64_GOT64":"c","R_X86_64_GOTOFF64":"c","R_X86_64_GOTPC32":"c","R_X86_64_GOTPC32_TLSDESC":"c","R_X86_64_GOTPC64":"c","R_X86_64_GOTPCREL":"c","R_X86_64_GOTPCREL64":"c","R_X86_64_GOTPCRELX":"c","R_X86_64_GOTPLT64":"c","R_X86_64_GOTTPOFF":"c","R_X86_64_IRELATIVE":"c","R_X86_64_JMP_SLOT":"c","R_X86_64_NONE":"c","R_X86_64_PC16":"c","R_X86_64_PC32":"c","R_X86_64_PC32_BND":"c","R_X86_64_PC64":"c","R_X86_64_PC8":"c","R_X86_64_PLT32":"c","R_X86_64_PLT32_BND":"c","R_X86_64_PLTOFF64":"c","R_X86_64_RELATIVE":"c","R_X86_64_RELATIVE64":"c","R_X86_64_REX_GOTPCRELX":"c","R_X86_64_SIZE32":"c","R_X86_64_SIZE64":"c","R_X86_64_TLSDESC":"c","R_X86_64_TLSDESC_CALL":"c","R_X86_64_TLSGD":"c","R_X86_64_TLSLD":"c","R_X86_64_TPOFF32":"c","R_X86_64_TPOFF64":"c","Rel32":"t","Rel64":"t","Rela32":"t","Rela64":"t","SHF_ALLOC":"c","SHF_COMPRESSED":"c","SHF_EXECINSTR":"c","SHF_GROUP":"c","SHF_INFO_LINK":"c","SHF_LINK_ORDER":"c","SHF_MASKOS":"c","SHF_MASKPROC":"c","SHF_MERGE":"c","SHF_OS_NONCONFORMING":"c","SHF_STRINGS":"c","SHF_TLS":"c","SHF_WRITE":"c","SHN_ABS":"c","SHN_COMMON":"c","SHN_HIOS":"c","SHN_HIPROC":"c","SHN_HIRESERVE":"c","SHN_LOOS":"c","SHN_LOPROC":"c","SHN_LORESERVE":"c","SHN_UNDEF":"c","SHN_XINDEX":"c","SHT_DYNAMIC":"c","SHT_DYNSYM":"c","SHT_FINI_ARRAY":"c","SHT_GNU_ATTRIBUTES":"c","SHT_GNU_HASH":"c","SHT_GNU_LIBLIST":"c","SHT_GNU_VERDEF":"c","SHT_GNU_VERNEED":"c","SHT_GNU_VERSYM":"c","SHT_GROUP":"c","SHT_HASH":"c","SHT_HIOS":"c","SHT_HIPROC":"c","SHT_HIUSER":"c","SHT_INIT_ARRAY":"c","SHT_LOOS":"c","SHT_LOPROC":"c","SHT_LOUSER":"c","SHT_MIPS_ABIFLAGS":"c","SHT_NOBITS":"c","SHT_NOTE":"c","SHT_NULL":"c","SHT_PREINIT_ARRAY":"c","SHT_PROGBITS":"c","SHT_REL":"c","SHT_RELA":"c","SHT_RISCV_ATTRIBUTES":"c","SHT_SHLIB":"c","SHT_STRTAB":"c","SHT_SYMTAB":"c","SHT_SYMTAB_SHNDX":"c","STB_GLOBAL":"c","STB_HIOS":"c","STB_HIPROC":"c","STB_LOCAL":"c","STB_LOOS":"c","STB_LOPROC":"c","STB_WEAK":"c","STT_COMMON":"c","STT_FILE":"c","STT_FUNC":"c","STT_GNU_IFUNC":"c","STT_HIOS":"c","STT_HIPROC":"c","STT_LOOS":"c","STT_LOPROC":"c","STT_NOTYPE":"c","STT_OBJECT":"c","STT_RELC":"c","STT_SECTION":"c","STT_SRELC":"c","STT_TLS":"c","STV_DEFAULT":"c","STV_HIDDEN":"c","STV_INTERNAL":"c","STV_PROTECTED":"c","ST_BIND":"f","ST_INFO":"f","ST_TYPE":"f","ST_VISIBILITY":"f","Section":"t","Section.Data":"m","Section.Open":"m","Section32":"t","Section64":"t","SectionFlag":"t","SectionFlag.GoString":"m","SectionFlag.String":"m","SectionHeader":"t","SectionIndex":"t","SectionIndex.GoString":"m","SectionIndex.String":"m","SectionType":"t","SectionType.GoString":"m","SectionType.String":"m","Sym32":"t","Sym32Size":"c","Sym64":"t","Sym64Size":"c","SymBind":"t","SymBind.GoString":"m","SymBind.String":"m","SymType":"t","SymType.GoString":"m","SymType.String":"m","SymVis":"t","SymVis.GoString":"m","SymVis.String":"m","Symbol":"t","Type":"t","Type.GoString":"m","Type.String":"m","VER_FLG_BASE":"c","VER_FLG_INFO":"c","VER_FLG_WEAK":"c","Version":"t","Version.GoString":"m","Version.String":"m","VersionIndex":"t","VersionIndex.Index":"m","VersionIndex.IsHidden":"m"}},"debug/gosym":{"path":"debug/gosym","name":"gosym","symbols":{"DecodingError":"t","DecodingError.Error":"m","Func":"t","LineTable":"t","LineTable.LineToPC":"m","LineTable.PCToLine":"m","NewLineTable":"f","NewTable":"f","Obj":"t","Sym":"t","Sym.BaseName":"m","Sym.PackageName":"m","Sym.ReceiverName":"m","Sym.Static":"m","Table":"t","Table.LineToPC":"m","Table.LookupFunc":"m","Table.LookupSym":"m","Table.PCToFunc":"m","Table.PCToLine":"m","Table.SymByAddr":"m","UnknownFileError":"t","UnknownFileError.Error":"m","UnknownLineError":"t","UnknownLineError.Error":"m"}},"debug/macho":{"path":"debug/macho","name":"macho","symbols":{"ARM64_RELOC_ADDEND":"c","ARM64_RELOC_BRANCH26":"c","ARM64_RELOC_GOT_LOAD_PAGE21":"c","ARM64_RELOC_GOT_LOAD_PAGEOFF12":"c","ARM64_RELOC_PAGE21":"c","ARM64_RELOC_PAGEOFF12":"c","ARM64_RELOC_POINTER_TO_GOT":"c","ARM64_RELOC_SUBTRACTOR":"c","ARM64_RELOC_TLVP_LOAD_PAGE21":"c","ARM64_RELOC_TLVP_LOAD_PAGEOFF12":"c","ARM64_RELOC_UNSIGNED":"c","ARM_RELOC_BR24":"c","ARM_RELOC_HALF":"c","ARM_RELOC_HALF_SECTDIFF":"c","ARM_RELOC_LOCAL_SECTDIFF":"c","ARM_RELOC_PAIR":"c","ARM_RELOC_PB_LA_PTR":"c","ARM_RELOC_SECTDIFF":"c","ARM_RELOC_VANILLA":"c","ARM_THUMB_32BIT_BRANCH":"c","ARM_THUMB_RELOC_BR22":"c","Cpu":"t","Cpu.GoString":"m","Cpu.String":"m","Cpu386":"c","CpuAmd64":"c","CpuArm":"c","CpuArm64":"c","CpuPpc":"c","CpuPpc64":"c","Dylib":"t","DylibCmd":"t","Dysymtab":"t","DysymtabCmd":"t","ErrNotFat":"v","FatArch":"t","FatArchHeader":"t","FatFile":"t","FatFile.Close":"m","File":"t","File.Close":"m","File.DWARF":"m","File.ImportedLibraries":"m","File.ImportedSymbols":"m","File.Section":"m","File.Segment":"m","FileHeader":"t","FlagAllModsBound":"c","FlagAllowStackExecution":"c","FlagAppExtensionSafe":"c","FlagBindAtLoad":"c","FlagBindsToWeak":"c","FlagCanonical":"c","FlagDeadStrippableDylib":"c","FlagDyldLink":"c","FlagForceFlat":"c","FlagHasTLVDescriptors":"c","FlagIncrLink":"c","FlagLazyInit":"c","FlagNoFixPrebinding":"c","FlagNoHeapExecution":"c","FlagNoMultiDefs":"c","FlagNoReexportedDylibs":"c","FlagNoUndefs":"c","FlagPIE":"c","FlagPrebindable":"c","FlagPrebound":"c","FlagRootSafe":"c","FlagSetuidSafe":"c","FlagSplitSegs":"c","FlagSubsectionsViaSymbols":"c","FlagTwoLevel":"c","FlagWeakDefines":"c","FormatError":"t","FormatError.Error":"m","GENERIC_RELOC_LOCAL_SECTDIFF":"c","GENERIC_RELOC_PAIR":"c","GENERIC_RELOC_PB_LA_PTR":"c","GENERIC_RELOC_SECTDIFF":"c","GENERIC_RELOC_TLV":"c","GENERIC_RELOC_VANILLA":"c","Load":"t","LoadBytes":"t","LoadBytes.Raw":"m","LoadCmd":"t","LoadCmd.GoString":"m","LoadCmd.String":"m","LoadCmdDylib":"c","LoadCmdDylinker":"c","LoadCmdDysymtab":"c","LoadCmdRpath":"c","LoadCmdSegment":"c","LoadCmdSegment64":"c","LoadCmdSymtab":"c","LoadCmdThread":"c","LoadCmdUnixThread":"c","Magic32":"c","Magic64":"c","MagicFat":"c","NewFatFile":"f","NewFile":"f","Nlist32":"t","Nlist64":"t","Open":"f","OpenFat":"f","Regs386":"t","RegsAMD64":"t","Reloc":"t","RelocTypeARM":"t","RelocTypeARM.GoString":"m","RelocTypeARM.String":"m","RelocTypeARM64":"t","RelocTypeARM64.GoString":"m","RelocTypeARM64.String":"m","RelocTypeGeneric":"t","RelocTypeGeneric.GoString":"m","RelocTypeGeneric.String":"m","RelocTypeX86_64":"t","RelocTypeX86_64.GoString":"m","RelocTypeX86_64.String":"m","Rpath":"t","RpathCmd":"t","Section":"t","Section.Data":"m","Section.Open":"m","Section32":"t","Section64":"t","SectionHeader":"t","Segment":"t","Segment.Data":"m","Segment.Open":"m","Segment32":"t","Segment64":"t","SegmentHeader":"t","Symbol":"t","Symtab":"t","SymtabCmd":"t","Thread":"t","Type":"t","Type.GoString":"m","Type.String":"m","TypeBundle":"c","TypeDylib":"c","TypeExec":"c","TypeObj":"c","X86_64_RELOC_BRANCH":"c","X86_64_RELOC_GOT":"c","X86_64_RELOC_GOT_LOAD":"c","X86_64_RELOC_SIGNED":"c","X86_64_RELOC_SIGNED_1":"c","X86_64_RELOC_SIGNED_2":"c","X86_64_RELOC_SIGNED_4":"c","X86_64_RELOC_SUBTRACTOR":"c","X86_64_RELOC_TLV":"c","X86_64_RELOC_UNSIGNED":"c"}},"debug/pe":{"path":"debug/pe","name":"pe","symbols":{"COFFSymbol":"t","COFFSymbol.FullName":"m","COFFSymbolAuxFormat5":"t","COFFSymbolSize":"c","DataDirectory":"t","File":"t","File.COFFSymbolReadSectionDefAux":"m","File.Close":"m","File.DWARF":"m","File.ImportedLibraries":"m","File.ImportedSymbols":"m","File.Section":"m","FileHeader":"t","FormatError":"t","FormatError.Error":"m","IMAGE_COMDAT_SELECT_ANY":"c","IMAGE_COMDAT_SELECT_ASSOCIATIVE":"c","IMAGE_COMDAT_SELECT_EXACT_MATCH":"c","IMAGE_COMDAT_SELECT_LARGEST":"c","IMAGE_COMDAT_SELECT_NODUPLICATES":"c","IMAGE_COMDAT_SELECT_SAME_SIZE":"c","IMAGE_DIRECTORY_ENTRY_ARCHITECTURE":"c","IMAGE_DIRECTORY_ENTRY_BASERELOC":"c","IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT":"c","IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR":"c","IMAGE_DIRECTORY_ENTRY_DEBUG":"c","IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT":"c","IMAGE_DIRECTORY_ENTRY_EXCEPTION":"c","IMAGE_DIRECTORY_ENTRY_EXPORT":"c","IMAGE_DIRECTORY_ENTRY_GLOBALPTR":"c","IMAGE_DIRECTORY_ENTRY_IAT":"c","IMAGE_DIRECTORY_ENTRY_IMPORT":"c","IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG":"c","IMAGE_DIRECTORY_ENTRY_RESOURCE":"c","IMAGE_DIRECTORY_ENTRY_SECURITY":"c","IMAGE_DIRECTORY_ENTRY_TLS":"c","IMAGE_DLLCHARACTERISTICS_APPCONTAINER":"c","IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE":"c","IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY":"c","IMAGE_DLLCHARACTERISTICS_GUARD_CF":"c","IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA":"c","IMAGE_DLLCHARACTERISTICS_NO_BIND":"c","IMAGE_DLLCHARACTERISTICS_NO_ISOLATION":"c","IMAGE_DLLCHARACTERISTICS_NO_SEH":"c","IMAGE_DLLCHARACTERISTICS_NX_COMPAT":"c","IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE":"c","IMAGE_DLLCHARACTERISTICS_WDM_DRIVER":"c","IMAGE_FILE_32BIT_MACHINE":"c","IMAGE_FILE_AGGRESIVE_WS_TRIM":"c","IMAGE_FILE_BYTES_REVERSED_HI":"c","IMAGE_FILE_BYTES_REVERSED_LO":"c","IMAGE_FILE_DEBUG_STRIPPED":"c","IMAGE_FILE_DLL":"c","IMAGE_FILE_EXECUTABLE_IMAGE":"c","IMAGE_FILE_LARGE_ADDRESS_AWARE":"c","IMAGE_FILE_LINE_NUMS_STRIPPED":"c","IMAGE_FILE_LOCAL_SYMS_STRIPPED":"c","IMAGE_FILE_MACHINE_AM33":"c","IMAGE_FILE_MACHINE_AMD64":"c","IMAGE_FILE_MACHINE_ARM":"c","IMAGE_FILE_MACHINE_ARM64":"c","IMAGE_FILE_MACHINE_ARMNT":"c","IMAGE_FILE_MACHINE_EBC":"c","IMAGE_FILE_MACHINE_I386":"c","IMAGE_FILE_MACHINE_IA64":"c","IMAGE_FILE_MACHINE_LOONGARCH32":"c","IMAGE_FILE_MACHINE_LOONGARCH64":"c","IMAGE_FILE_MACHINE_M32R":"c","IMAGE_FILE_MACHINE_MIPS16":"c","IMAGE_FILE_MACHINE_MIPSFPU":"c","IMAGE_FILE_MACHINE_MIPSFPU16":"c","IMAGE_FILE_MACHINE_POWERPC":"c","IMAGE_FILE_MACHINE_POWERPCFP":"c","IMAGE_FILE_MACHINE_R4000":"c","IMAGE_FILE_MACHINE_RISCV128":"c","IMAGE_FILE_MACHINE_RISCV32":"c","IMAGE_FILE_MACHINE_RISCV64":"c","IMAGE_FILE_MACHINE_SH3":"c","IMAGE_FILE_MACHINE_SH3DSP":"c","IMAGE_FILE_MACHINE_SH4":"c","IMAGE_FILE_MACHINE_SH5":"c","IMAGE_FILE_MACHINE_THUMB":"c","IMAGE_FILE_MACHINE_UNKNOWN":"c","IMAGE_FILE_MACHINE_WCEMIPSV2":"c","IMAGE_FILE_NET_RUN_FROM_SWAP":"c","IMAGE_FILE_RELOCS_STRIPPED":"c","IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP":"c","IMAGE_FILE_SYSTEM":"c","IMAGE_FILE_UP_SYSTEM_ONLY":"c","IMAGE_SCN_CNT_CODE":"c","IMAGE_SCN_CNT_INITIALIZED_DATA":"c","IMAGE_SCN_CNT_UNINITIALIZED_DATA":"c","IMAGE_SCN_LNK_COMDAT":"c","IMAGE_SCN_MEM_DISCARDABLE":"c","IMAGE_SCN_MEM_EXECUTE":"c","IMAGE_SCN_MEM_READ":"c","IMAGE_SCN_MEM_WRITE":"c","IMAGE_SUBSYSTEM_EFI_APPLICATION":"c","IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER":"c","IMAGE_SUBSYSTEM_EFI_ROM":"c","IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER":"c","IMAGE_SUBSYSTEM_NATIVE":"c","IMAGE_SUBSYSTEM_NATIVE_WINDOWS":"c","IMAGE_SUBSYSTEM_OS2_CUI":"c","IMAGE_SUBSYSTEM_POSIX_CUI":"c","IMAGE_SUBSYSTEM_UNKNOWN":"c","IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION":"c","IMAGE_SUBSYSTEM_WINDOWS_CE_GUI":"c","IMAGE_SUBSYSTEM_WINDOWS_CUI":"c","IMAGE_SUBSYSTEM_WINDOWS_GUI":"c","IMAGE_SUBSYSTEM_XBOX":"c","ImportDirectory":"t","NewFile":"f","Open":"f","OptionalHeader32":"t","OptionalHeader64":"t","Reloc":"t","Section":"t","Section.Data":"m","Section.Open":"m","SectionHeader":"t","SectionHeader32":"t","StringTable":"t","StringTable.String":"m","Symbol":"t"}},"debug/plan9obj":{"path":"debug/plan9obj","name":"plan9obj","symbols":{"ErrNoSymbols":"v","File":"t","File.Close":"m","File.Section":"m","File.Symbols":"m","FileHeader":"t","Magic386":"c","Magic64":"c","MagicAMD64":"c","MagicARM":"c","NewFile":"f","Open":"f","Section":"t","Section.Data":"m","Section.Open":"m","SectionHeader":"t","Sym":"t"}},"embed":{"path":"embed","name":"embed","symbols":{"FS":"t","FS.Open":"m","FS.ReadDir":"m","FS.ReadFile":"m"}},"encoding":{"path":"encoding","name":"encoding","symbols":{"BinaryAppender":"t","BinaryMarshaler":"t","BinaryUnmarshaler":"t","TextAppender":"t","TextMarshaler":"t","TextUnmarshaler":"t"}},"encoding/ascii85":{"path":"encoding/ascii85","name":"ascii85","symbols":{"CorruptInputError":"t","CorruptInputError.Error":"m","Decode":"f","Encode":"f","MaxEncodedLen":"f","NewDecoder":"f","NewEncoder":"f"}},"encoding/asn1":{"path":"encoding/asn1","name":"asn1","symbols":{"BitString":"t","BitString.At":"m","BitString.RightAlign":"m","ClassApplication":"c","ClassContextSpecific":"c","ClassPrivate":"c","ClassUniversal":"c","Enumerated":"t","Flag":"t","Marshal":"f","MarshalWithParams":"f","NullBytes":"v","NullRawValue":"v","ObjectIdentifier":"t","ObjectIdentifier.Equal":"m","ObjectIdentifier.String":"m","RawContent":"t","RawValue":"t","StructuralError":"t","StructuralError.Error":"m","SyntaxError":"t","SyntaxError.Error":"m","TagBMPString":"c","TagBitString":"c","TagBoolean":"c","TagEnum":"c","TagGeneralString":"c","TagGeneralizedTime":"c","TagIA5String":"c","TagInteger":"c","TagNull":"c","TagNumericString":"c","TagOID":"c","TagOctetString":"c","TagPrintableString":"c","TagSequence":"c","TagSet":"c","TagT61String":"c","TagUTCTime":"c","TagUTF8String":"c","Unmarshal":"f","UnmarshalWithParams":"f"}},"encoding/base32":{"path":"encoding/base32","name":"base32","symbols":{"CorruptInputError":"t","CorruptInputError.Error":"m","Encoding":"t","Encoding.AppendDecode":"m","Encoding.AppendEncode":"m","Encoding.Decode":"m","Encoding.DecodeString":"m","Encoding.DecodedLen":"m","Encoding.Encode":"m","Encoding.EncodeToString":"m","Encoding.EncodedLen":"m","Encoding.WithPadding":"m","HexEncoding":"v","NewDecoder":"f","NewEncoder":"f","NewEncoding":"f","NoPadding":"c","StdEncoding":"v","StdPadding":"c"}},"encoding/base64":{"path":"encoding/base64","name":"base64","symbols":{"CorruptInputError":"t","CorruptInputError.Error":"m","Encoding":"t","Encoding.AppendDecode":"m","Encoding.AppendEncode":"m","Encoding.Decode":"m","Encoding.DecodeString":"m","Encoding.DecodedLen":"m","Encoding.Encode":"m","Encoding.EncodeToString":"m","Encoding.EncodedLen":"m","Encoding.Strict":"m","Encoding.WithPadding":"m","NewDecoder":"f","NewEncoder":"f","NewEncoding":"f","NoPadding":"c","RawStdEncoding":"v","RawURLEncoding":"v","StdEncoding":"v","StdPadding":"c","URLEncoding":"v"}},"encoding/binary":{"path":"encoding/binary","name":"binary","symbols":{"Append":"f","AppendByteOrder":"t","AppendUvarint":"f","AppendVarint":"f","BigEndian":"v","ByteOrder":"t","Decode":"f","Encode":"f","LittleEndian":"v","MaxVarintLen16":"c","MaxVarintLen32":"c","MaxVarintLen64":"c","NativeEndian":"v","PutUvarint":"f","PutVarint":"f","Read":"f","ReadUvarint":"f","ReadVarint":"f","Size":"f","Uvarint":"f","Varint":"f","Write":"f"}},"encoding/csv":{"path":"encoding/csv","name":"csv","symbols":{"ErrBareQuote":"v","ErrFieldCount":"v","ErrQuote":"v","ErrTrailingComma":"v","NewReader":"f","NewWriter":"f","ParseError":"t","ParseError.Error":"m","ParseError.Unwrap":"m","Reader":"t","Reader.FieldPos":"m","Reader.InputOffset":"m","Reader.Read":"m","Reader.ReadAll":"m","Writer":"t","Writer.Error":"m","Writer.Flush":"m","Writer.Write":"m","Writer.WriteAll":"m"}},"encoding/gob":{"path":"encoding/gob","name":"gob","symbols":{"CommonType":"t","Decoder":"t","Decoder.Decode":"m","Decoder.DecodeValue":"m","Encoder":"t","Encoder.Encode":"m","Encoder.EncodeValue":"m","GobDecoder":"t","GobEncoder":"t","NewDecoder":"f","NewEncoder":"f","Register":"f","RegisterName":"f"}},"encoding/hex":{"path":"encoding/hex","name":"hex","symbols":{"AppendDecode":"f","AppendEncode":"f","Decode":"f","DecodeString":"f","DecodedLen":"f","Dump":"f","Dumper":"f","Encode":"f","EncodeToString":"f","EncodedLen":"f","ErrLength":"v","InvalidByteError":"t","InvalidByteError.Error":"m","NewDecoder":"f","NewEncoder":"f"}},"encoding/json":{"path":"encoding/json","name":"json","symbols":{"Compact":"f","Decoder":"t","Decoder.Buffered":"m","Decoder.Decode":"m","Decoder.DisallowUnknownFields":"m","Decoder.InputOffset":"m","Decoder.More":"m","Decoder.Token":"m","Decoder.UseNumber":"m","Delim":"t","Delim.String":"m","Encoder":"t","Encoder.Encode":"m","Encoder.SetEscapeHTML":"m","Encoder.SetIndent":"m","HTMLEscape":"f","Indent":"f","InvalidUTF8Error":"t","InvalidUTF8Error.Error":"m","InvalidUnmarshalError":"t","InvalidUnmarshalError.Error":"m","Marshal":"f","MarshalIndent":"f","Marshaler":"t","MarshalerError":"t","MarshalerError.Error":"m","MarshalerError.Unwrap":"m","NewDecoder":"f","NewEncoder":"f","Number":"t","Number.Float64":"m","Number.Int64":"m","Number.String":"m","RawMessage":"t","RawMessage.MarshalJSON":"m","RawMessage.UnmarshalJSON":"m","SyntaxError":"t","SyntaxError.Error":"m","Token":"t","Unmarshal":"f","UnmarshalFieldError":"t","UnmarshalFieldError.Error":"m","UnmarshalTypeError":"t","UnmarshalTypeError.Error":"m","Unmarshaler":"t","UnsupportedTypeError":"t","UnsupportedTypeError.Error":"m","UnsupportedValueError":"t","UnsupportedValueError.Error":"m","Valid":"f"}},"encoding/pem":{"path":"encoding/pem","name":"pem","symbols":{"Block":"t","Decode":"f","Encode":"f","EncodeToMemory":"f"}},"encoding/xml":{"path":"encoding/xml","name":"xml","symbols":{"Attr":"t","CharData":"t","CharData.Copy":"m","Comment":"t","Comment.Copy":"m","CopyToken":"f","Decoder":"t","Decoder.Decode":"m","Decoder.DecodeElement":"m","Decoder.InputOffset":"m","Decoder.InputPos":"m","Decoder.RawToken":"m","Decoder.Skip":"m","Decoder.Token":"m","Directive":"t","Directive.Copy":"m","Encoder":"t","Encoder.Close":"m","Encoder.Encode":"m","Encoder.EncodeElement":"m","Encoder.EncodeToken":"m","Encoder.Flush":"m","Encoder.Indent":"m","EndElement":"t","Escape":"f","EscapeText":"f","HTMLAutoClose":"v","HTMLEntity":"v","Header":"c","Marshal":"f","MarshalIndent":"f","Marshaler":"t","MarshalerAttr":"t","Name":"t","NewDecoder":"f","NewEncoder":"f","NewTokenDecoder":"f","ProcInst":"t","ProcInst.Copy":"m","StartElement":"t","StartElement.Copy":"m","StartElement.End":"m","SyntaxError":"t","SyntaxError.Error":"m","TagPathError":"t","TagPathError.Error":"m","Token":"t","TokenReader":"t","Unmarshal":"f","UnmarshalError":"t","UnmarshalError.Error":"m","Unmarshaler":"t","UnmarshalerAttr":"t","UnsupportedTypeError":"t","UnsupportedTypeError.Error":"m"}},"errors":{"path":"errors","name":"errors","symbols":{"As":"f","ErrUnsupported":"v","Is":"f","Join":"f","New":"f","Unwrap":"f"}},"expvar":{"path":"expvar","name":"expvar","symbols":{"Do":"f","Float":"t","Float.Add":"m","Float.Set":"m","Float.String":"m","Float.Value":"m","Func":"t","Func.String":"m","Func.Value":"m","Get":"f","Handler":"f","Int":"t","Int.Add":"m","Int.Set":"m","Int.String":"m","Int.Value":"m","KeyValue":"t","Map":"t","Map.Add":"m","Map.AddFloat":"m","Map.Delete":"m","Map.Do":"m","Map.Get":"m","Map.Init":"m","Map.Set":"m","Map.String":"m","NewFloat":"f","NewInt":"f","NewMap":"f","NewString":"f","Publish":"f","String":"t","String.Set":"m","String.String":"m","String.Value":"m","Var":"t"}},"flag":{"path":"flag","name":"flag","symbols":{"Arg":"f","Args":"f","Bool":"f","BoolFunc":"f","BoolVar":"f","CommandLine":"v","ContinueOnError":"c","Duration":"f","DurationVar":"f","ErrHelp":"v","ErrorHandling":"t","ExitOnError":"c","Flag":"t","FlagSet":"t","FlagSet.Arg":"m","FlagSet.Args":"m","FlagSet.Bool":"m","FlagSet.BoolFunc":"m","FlagSet.BoolVar":"m","FlagSet.Duration":"m","FlagSet.DurationVar":"m","FlagSet.ErrorHandling":"m","FlagSet.Float64":"m","FlagSet.Float64Var":"m","FlagSet.Func":"m","FlagSet.Init":"m","FlagSet.Int":"m","FlagSet.Int64":"m","FlagSet.Int64Var":"m","FlagSet.IntVar":"m","FlagSet.Lookup":"m","FlagSet.NArg":"m","FlagSet.NFlag":"m","FlagSet.Name":"m","FlagSet.Output":"m","FlagSet.Parse":"m","FlagSet.Parsed":"m","FlagSet.PrintDefaults":"m","FlagSet.Set":"m","FlagSet.SetOutput":"m","FlagSet.String":"m","FlagSet.StringVar":"m","FlagSet.TextVar":"m","FlagSet.Uint":"m","FlagSet.Uint64":"m","FlagSet.Uint64Var":"m","FlagSet.UintVar":"m","FlagSet.Var":"m","FlagSet.Visit":"m","FlagSet.VisitAll":"m","Float64":"f","Float64Var":"f","Func":"f","Getter":"t","Int":"f","Int64":"f","Int64Var":"f","IntVar":"f","Lookup":"f","NArg":"f","NFlag":"f","NewFlagSet":"f","PanicOnError":"c","Parse":"f","Parsed":"f","PrintDefaults":"f","Set":"f","String":"f","StringVar":"f","TextVar":"f","Uint":"f","Uint64":"f","Uint64Var":"f","UintVar":"f","UnquoteUsage":"f","Usage":"v","Value":"t","Var":"f","Visit":"f","VisitAll":"f"}},"fmt":{"path":"fmt","name":"fmt","symbols":{"Append":"f","Appendf":"f","Appendln":"f","Errorf":"f","FormatString":"f","Formatter":"t","Fprint":"f","Fprintf":"f","Fprintln":"f","Fscan":"f","Fscanf":"f","Fscanln":"f","GoStringer":"t","Print":"f","Printf":"f","Println":"f","Scan":"f","ScanState":"t","Scanf":"f","Scanln":"f","Scanner":"t","Sprint":"f","Sprintf":"f","Sprintln":"f","Sscan":"f","Sscanf":"f","Sscanln":"f","State":"t","Stringer":"t"}},"go/ast":{"path":"go/ast","name":"ast","symbols":{"ArrayType":"t","ArrayType.End":"m","ArrayType.Pos":"m","AssignStmt":"t","AssignStmt.End":"m","AssignStmt.Pos":"m","Bad":"c","BadDecl":"t","BadDecl.End":"m","BadDecl.Pos":"m","BadExpr":"t","BadExpr.End":"m","BadExpr.Pos":"m","BadStmt":"t","BadStmt.End":"m","BadStmt.Pos":"m","BasicLit":"t","BasicLit.End":"m","BasicLit.Pos":"m","BinaryExpr":"t","BinaryExpr.End":"m","BinaryExpr.Pos":"m","BlockStmt":"t","BlockStmt.End":"m","BlockStmt.Pos":"m","BranchStmt":"t","BranchStmt.End":"m","BranchStmt.Pos":"m","CallExpr":"t","CallExpr.End":"m","CallExpr.Pos":"m","CaseClause":"t","CaseClause.End":"m","CaseClause.Pos":"m","ChanDir":"t","ChanType":"t","ChanType.End":"m","ChanType.Pos":"m","CommClause":"t","CommClause.End":"m","CommClause.Pos":"m","Comment":"t","Comment.End":"m","Comment.Pos":"m","CommentGroup":"t","CommentGroup.End":"m","CommentGroup.Pos":"m","CommentGroup.Text":"m","CommentMap":"t","CommentMap.Comments":"m","CommentMap.Filter":"m","CommentMap.String":"m","CommentMap.Update":"m","CompositeLit":"t","CompositeLit.End":"m","CompositeLit.Pos":"m","Con":"c","Decl":"t","DeclStmt":"t","DeclStmt.End":"m","DeclStmt.Pos":"m","DeferStmt":"t","DeferStmt.End":"m","DeferStmt.Pos":"m","Ellipsis":"t","Ellipsis.End":"m","Ellipsis.Pos":"m","EmptyStmt":"t","EmptyStmt.End":"m","EmptyStmt.Pos":"m","Expr":"t","ExprStmt":"t","ExprStmt.End":"m","ExprStmt.Pos":"m","Field":"t","Field.End":"m","Field.Pos":"m","FieldFilter":"t","FieldList":"t","FieldList.End":"m","FieldList.NumFields":"m","FieldList.Pos":"m","File":"t","File.End":"m","File.Pos":"m","FileExports":"f","Filter":"t","FilterDecl":"f","FilterFile":"f","FilterFuncDuplicates":"c","FilterImportDuplicates":"c","FilterPackage":"f","FilterUnassociatedComments":"c","ForStmt":"t","ForStmt.End":"m","ForStmt.Pos":"m","Fprint":"f","Fun":"c","FuncDecl":"t","FuncDecl.End":"m","FuncDecl.Pos":"m","FuncLit":"t","FuncLit.End":"m","FuncLit.Pos":"m","FuncType":"t","FuncType.End":"m","FuncType.Pos":"m","GenDecl":"t","GenDecl.End":"m","GenDecl.Pos":"m","GoStmt":"t","GoStmt.End":"m","GoStmt.Pos":"m","Ident":"t","Ident.End":"m","Ident.IsExported":"m","Ident.Pos":"m","Ident.String":"m","IfStmt":"t","IfStmt.End":"m","IfStmt.Pos":"m","ImportSpec":"t","ImportSpec.End":"m","ImportSpec.Pos":"m","Importer":"t","IncDecStmt":"t","IncDecStmt.End":"m","IncDecStmt.Pos":"m","IndexExpr":"t","IndexExpr.End":"m","IndexExpr.Pos":"m","IndexListExpr":"t","IndexListExpr.End":"m","IndexListExpr.Pos":"m","Inspect":"f","InterfaceType":"t","InterfaceType.End":"m","InterfaceType.Pos":"m","IsExported":"f","IsGenerated":"f","KeyValueExpr":"t","KeyValueExpr.End":"m","KeyValueExpr.Pos":"m","LabeledStmt":"t","LabeledStmt.End":"m","LabeledStmt.Pos":"m","Lbl":"c","MapType":"t","MapType.End":"m","MapType.Pos":"m","MergeMode":"t","MergePackageFiles":"f","NewCommentMap":"f","NewIdent":"f","NewObj":"f","NewPackage":"f","NewScope":"f","Node":"t","NotNilFilter":"f","ObjKind":"t","ObjKind.String":"m","Object":"t","Object.Pos":"m","Package":"t","Package.End":"m","Package.Pos":"m","PackageExports":"f","ParenExpr":"t","ParenExpr.End":"m","ParenExpr.Pos":"m","Pkg":"c","Preorder":"f","PreorderStack":"f","Print":"f","RECV":"c","RangeStmt":"t","RangeStmt.End":"m","RangeStmt.Pos":"m","ReturnStmt":"t","ReturnStmt.End":"m","ReturnStmt.Pos":"m","SEND":"c","Scope":"t","Scope.Insert":"m","Scope.Lookup":"m","Scope.String":"m","SelectStmt":"t","SelectStmt.End":"m","SelectStmt.Pos":"m","SelectorExpr":"t","SelectorExpr.End":"m","SelectorExpr.Pos":"m","SendStmt":"t","SendStmt.End":"m","SendStmt.Pos":"m","SliceExpr":"t","SliceExpr.End":"m","SliceExpr.Pos":"m","SortImports":"f","Spec":"t","StarExpr":"t","StarExpr.End":"m","StarExpr.Pos":"m","Stmt":"t","StructType":"t","StructType.End":"m","StructType.Pos":"m","SwitchStmt":"t","SwitchStmt.End":"m","SwitchStmt.Pos":"m","Typ":"c","TypeAssertExpr":"t","TypeAssertExpr.End":"m","TypeAssertExpr.Pos":"m","TypeSpec":"t","TypeSpec.End":"m","TypeSpec.Pos":"m","TypeSwitchStmt":"t","TypeSwitchStmt.End":"m","TypeSwitchStmt.Pos":"m","UnaryExpr":"t","UnaryExpr.End":"m","UnaryExpr.Pos":"m","Unparen":"f","ValueSpec":"t","ValueSpec.End":"m","ValueSpec.Pos":"m","Var":"c","Visitor":"t","Walk":"f"}},"go/build":{"path":"go/build","name":"build","symbols":{"AllowBinary":"c","ArchChar":"f","Context":"t","Context.Import":"m","Context.ImportDir":"m","Context.MatchFile":"m","Context.SrcDirs":"m","Default":"v","Directive":"t","FindOnly":"c","IgnoreVendor":"c","Import":"f","ImportComment":"c","ImportDir":"f","ImportMode":"t","IsLocalImport":"f","MultiplePackageError":"t","MultiplePackageError.Error":"m","NoGoError":"t","NoGoError.Error":"m","Package":"t","Package.IsCommand":"m","ToolDir":"v"}},"go/build/constraint":{"path":"go/build/constraint","name":"constraint","symbols":{"AndExpr":"t","AndExpr.Eval":"m","AndExpr.String":"m","Expr":"t","GoVersion":"f","IsGoBuild":"f","IsPlusBuild":"f","NotExpr":"t","NotExpr.Eval":"m","NotExpr.String":"m","OrExpr":"t","OrExpr.Eval":"m","OrExpr.String":"m","Parse":"f","PlusBuildLines":"f","SyntaxError":"t","SyntaxError.Error":"m","TagExpr":"t","TagExpr.Eval":"m","TagExpr.String":"m"}},"go/constant":{"path":"go/constant","name":"constant","symbols":{"BinaryOp":"f","BitLen":"f","Bool":"c","BoolVal":"f","Bytes":"f","Compare":"f","Complex":"c","Denom":"f","Float":"c","Float32Val":"f","Float64Val":"f","Imag":"f","Int":"c","Int64Val":"f","Kind":"t","Kind.String":"m","Make":"f","MakeBool":"f","MakeFloat64":"f","MakeFromBytes":"f","MakeFromLiteral":"f","MakeImag":"f","MakeInt64":"f","MakeString":"f","MakeUint64":"f","MakeUnknown":"f","Num":"f","Real":"f","Shift":"f","Sign":"f","String":"c","StringVal":"f","ToComplex":"f","ToFloat":"f","ToInt":"f","Uint64Val":"f","UnaryOp":"f","Unknown":"c","Val":"f","Value":"t"}},"go/doc":{"path":"go/doc","name":"doc","symbols":{"AllDecls":"c","AllMethods":"c","Example":"t","Examples":"f","Filter":"t","Func":"t","IllegalPrefixes":"v","IsPredeclared":"f","Mode":"t","New":"f","NewFromFiles":"f","Note":"t","Package":"t","Package.Filter":"m","Package.HTML":"m","Package.Markdown":"m","Package.Parser":"m","Package.Printer":"m","Package.Synopsis":"m","Package.Text":"m","PreserveAST":"c","Synopsis":"f","ToHTML":"f","ToText":"f","Type":"t","Value":"t"}},"go/doc/comment":{"path":"go/doc/comment","name":"comment","symbols":{"Block":"t","Code":"t","DefaultLookupPackage":"f","Doc":"t","DocLink":"t","DocLink.DefaultURL":"m","Heading":"t","Heading.DefaultID":"m","Italic":"t","Link":"t","LinkDef":"t","List":"t","List.BlankBefore":"m","List.BlankBetween":"m","ListItem":"t","Paragraph":"t","Parser":"t","Parser.Parse":"m","Plain":"t","Printer":"t","Printer.Comment":"m","Printer.HTML":"m","Printer.Markdown":"m","Printer.Text":"m","Text":"t"}},"go/format":{"path":"go/format","name":"format","symbols":{"Node":"f","Source":"f"}},"go/importer":{"path":"go/importer","name":"importer","symbols":{"Default":"f","For":"f","ForCompiler":"f","Lookup":"t"}},"go/parser":{"path":"go/parser","name":"parser","symbols":{"AllErrors":"c","DeclarationErrors":"c","ImportsOnly":"c","Mode":"t","PackageClauseOnly":"c","ParseComments":"c","ParseDir":"f","ParseExpr":"f","ParseExprFrom":"f","ParseFile":"f","SkipObjectResolution":"c","SpuriousErrors":"c","Trace":"c"}},"go/printer":{"path":"go/printer","name":"printer","symbols":{"CommentedNode":"t","Config":"t","Config.Fprint":"m","Fprint":"f","Mode":"t","RawFormat":"c","SourcePos":"c","TabIndent":"c","UseSpaces":"c"}},"go/scanner":{"path":"go/scanner","name":"scanner","symbols":{"Error":"t","Error.Error":"m","ErrorHandler":"t","ErrorList":"t","ErrorList.Add":"m","ErrorList.Err":"m","ErrorList.Error":"m","ErrorList.Len":"m","ErrorList.Less":"m","ErrorList.RemoveMultiples":"m","ErrorList.Reset":"m","ErrorList.Sort":"m","ErrorList.Swap":"m","Mode":"t","PrintError":"f","ScanComments":"c","Scanner":"t","Scanner.Init":"m","Scanner.Scan":"m"}},"go/token":{"path":"go/token","name":"token","symbols":{"ADD":"c","ADD_ASSIGN":"c","AND":"c","AND_ASSIGN":"c","AND_NOT":"c","AND_NOT_ASSIGN":"c","ARROW":"c","ASSIGN":"c","BREAK":"c","CASE":"c","CHAN":"c","CHAR":"c","COLON":"c","COMMA":"c","COMMENT":"c","CONST":"c","CONTINUE":"c","DEC":"c","DEFAULT":"c","DEFER":"c","DEFINE":"c","ELLIPSIS":"c","ELSE":"c","EOF":"c","EQL":"c","FALLTHROUGH":"c","FLOAT":"c","FOR":"c","FUNC":"c","File":"t","File.AddLine":"m","File.AddLineColumnInfo":"m","File.AddLineInfo":"m","File.Base":"m","File.Line":"m","File.LineCount":"m","File.LineStart":"m","File.Lines":"m","File.MergeLine":"m","File.Name":"m","File.Offset":"m","File.Pos":"m","File.Position":"m","File.PositionFor":"m","File.SetLines":"m","File.SetLinesForContent":"m","File.Size":"m","FileSet":"t","FileSet.AddExistingFiles":"m","FileSet.AddFile":"m","FileSet.Base":"m","FileSet.File":"m","FileSet.Iterate":"m","FileSet.Position":"m","FileSet.PositionFor":"m","FileSet.Read":"m","FileSet.RemoveFile":"m","FileSet.Write":"m","GEQ":"c","GO":"c","GOTO":"c","GTR":"c","HighestPrec":"c","IDENT":"c","IF":"c","ILLEGAL":"c","IMAG":"c","IMPORT":"c","INC":"c","INT":"c","INTERFACE":"c","IsExported":"f","IsIdentifier":"f","IsKeyword":"f","LAND":"c","LBRACE":"c","LBRACK":"c","LEQ":"c","LOR":"c","LPAREN":"c","LSS":"c","Lookup":"f","LowestPrec":"c","MAP":"c","MUL":"c","MUL_ASSIGN":"c","NEQ":"c","NOT":"c","NewFileSet":"f","NoPos":"c","OR":"c","OR_ASSIGN":"c","PACKAGE":"c","PERIOD":"c","Pos":"t","Pos.IsValid":"m","Position":"t","Position.IsValid":"m","Position.String":"m","QUO":"c","QUO_ASSIGN":"c","RANGE":"c","RBRACE":"c","RBRACK":"c","REM":"c","REM_ASSIGN":"c","RETURN":"c","RPAREN":"c","SELECT":"c","SEMICOLON":"c","SHL":"c","SHL_ASSIGN":"c","SHR":"c","SHR_ASSIGN":"c","STRING":"c","STRUCT":"c","SUB":"c","SUB_ASSIGN":"c","SWITCH":"c","TILDE":"c","TYPE":"c","Token":"t","Token.IsKeyword":"m","Token.IsLiteral":"m","Token.IsOperator":"m","Token.Precedence":"m","Token.String":"m","UnaryPrec":"c","VAR":"c","XOR":"c","XOR_ASSIGN":"c"}},"go/types":{"path":"go/types","name":"types","symbols":{"Alias":"t","Alias.Obj":"m","Alias.Origin":"m","Alias.Rhs":"m","Alias.SetTypeParams":"m","Alias.String":"m","Alias.TypeArgs":"m","Alias.TypeParams":"m","Alias.Underlying":"m","ArgumentError":"t","ArgumentError.Error":"m","ArgumentError.Unwrap":"m","Array":"t","Array.Elem":"m","Array.Len":"m","Array.String":"m","Array.Underlying":"m","AssertableTo":"f","AssignableTo":"f","Basic":"t","Basic.Info":"m","Basic.Kind":"m","Basic.Name":"m","Basic.String":"m","Basic.Underlying":"m","BasicInfo":"t","BasicKind":"t","Bool":"c","Builtin":"t","Builtin.String":"m","Byte":"c","Chan":"t","Chan.Dir":"m","Chan.Elem":"m","Chan.String":"m","Chan.Underlying":"m","ChanDir":"t","CheckExpr":"f","Checker":"t","Checker.Files":"m","Comparable":"f","Complex128":"c","Complex64":"c","Config":"t","Config.Check":"m","Const":"t","Const.String":"m","Const.Val":"m","Context":"t","ConvertibleTo":"f","DefPredeclaredTestFuncs":"f","Default":"f","Error":"t","Error.Error":"m","Eval":"f","ExprString":"f","FieldVal":"c","FieldVar":"c","Float32":"c","Float64":"c","Func":"t","Func.FullName":"m","Func.Origin":"m","Func.Pkg":"m","Func.Scope":"m","Func.Signature":"m","Func.String":"m","Id":"f","Identical":"f","IdenticalIgnoreTags":"f","Implements":"f","ImportMode":"t","Importer":"t","ImporterFrom":"t","Info":"t","Info.ObjectOf":"m","Info.PkgNameOf":"m","Info.TypeOf":"m","Initializer":"t","Initializer.String":"m","Instance":"t","Instantiate":"f","Int":"c","Int16":"c","Int32":"c","Int64":"c","Int8":"c","Interface":"t","Interface.Complete":"m","Interface.Embedded":"m","Interface.EmbeddedType":"m","Interface.EmbeddedTypes":"m","Interface.Empty":"m","Interface.ExplicitMethod":"m","Interface.ExplicitMethods":"m","Interface.IsComparable":"m","Interface.IsImplicit":"m","Interface.IsMethodSet":"m","Interface.MarkImplicit":"m","Interface.Method":"m","Interface.Methods":"m","Interface.NumEmbeddeds":"m","Interface.NumExplicitMethods":"m","Interface.NumMethods":"m","Interface.String":"m","Interface.Underlying":"m","Invalid":"c","IsBoolean":"c","IsComplex":"c","IsConstType":"c","IsFloat":"c","IsInteger":"c","IsInterface":"f","IsNumeric":"c","IsOrdered":"c","IsString":"c","IsUnsigned":"c","IsUntyped":"c","Label":"t","Label.String":"m","LocalVar":"c","LookupFieldOrMethod":"f","LookupSelection":"f","Map":"t","Map.Elem":"m","Map.Key":"m","Map.String":"m","Map.Underlying":"m","MethodExpr":"c","MethodSet":"t","MethodSet.At":"m","MethodSet.Len":"m","MethodSet.Lookup":"m","MethodSet.Methods":"m","MethodSet.String":"m","MethodVal":"c","MissingMethod":"f","Named":"t","Named.AddMethod":"m","Named.Method":"m","Named.Methods":"m","Named.NumMethods":"m","Named.Obj":"m","Named.Origin":"m","Named.SetTypeParams":"m","Named.SetUnderlying":"m","Named.String":"m","Named.TypeArgs":"m","Named.TypeParams":"m","Named.Underlying":"m","NewAlias":"f","NewArray":"f","NewChan":"f","NewChecker":"f","NewConst":"f","NewContext":"f","NewField":"f","NewFunc":"f","NewInterface":"f","NewInterfaceType":"f","NewLabel":"f","NewMap":"f","NewMethodSet":"f","NewNamed":"f","NewPackage":"f","NewParam":"f","NewPkgName":"f","NewPointer":"f","NewScope":"f","NewSignature":"f","NewSignatureType":"f","NewSlice":"f","NewStruct":"f","NewTerm":"f","NewTuple":"f","NewTypeName":"f","NewTypeParam":"f","NewUnion":"f","NewVar":"f","Nil":"t","Nil.String":"m","Object":"t","ObjectString":"f","Package":"t","Package.Complete":"m","Package.GoVersion":"m","Package.Imports":"m","Package.MarkComplete":"m","Package.Name":"m","Package.Path":"m","Package.Scope":"m","Package.SetImports":"m","Package.SetName":"m","Package.String":"m","PackageVar":"c","ParamVar":"c","PkgName":"t","PkgName.Imported":"m","PkgName.String":"m","Pointer":"t","Pointer.Elem":"m","Pointer.String":"m","Pointer.Underlying":"m","Qualifier":"t","RecvOnly":"c","RecvVar":"c","RelativeTo":"f","ResultVar":"c","Rune":"c","Satisfies":"f","Scope":"t","Scope.Child":"m","Scope.Children":"m","Scope.Contains":"m","Scope.End":"m","Scope.Innermost":"m","Scope.Insert":"m","Scope.Len":"m","Scope.Lookup":"m","Scope.LookupParent":"m","Scope.Names":"m","Scope.NumChildren":"m","Scope.Parent":"m","Scope.Pos":"m","Scope.String":"m","Scope.WriteTo":"m","Selection":"t","Selection.Index":"m","Selection.Indirect":"m","Selection.Kind":"m","Selection.Obj":"m","Selection.Recv":"m","Selection.String":"m","Selection.Type":"m","SelectionKind":"t","SelectionString":"f","SendOnly":"c","SendRecv":"c","Signature":"t","Signature.Params":"m","Signature.Recv":"m","Signature.RecvTypeParams":"m","Signature.Results":"m","Signature.String":"m","Signature.TypeParams":"m","Signature.Underlying":"m","Signature.Variadic":"m","Sizes":"t","SizesFor":"f","Slice":"t","Slice.Elem":"m","Slice.String":"m","Slice.Underlying":"m","StdSizes":"t","StdSizes.Alignof":"m","StdSizes.Offsetsof":"m","StdSizes.Sizeof":"m","String":"c","Struct":"t","Struct.Field":"m","Struct.Fields":"m","Struct.NumFields":"m","Struct.String":"m","Struct.Tag":"m","Struct.Underlying":"m","Term":"t","Term.String":"m","Term.Tilde":"m","Term.Type":"m","Tuple":"t","Tuple.At":"m","Tuple.Len":"m","Tuple.String":"m","Tuple.Underlying":"m","Tuple.Variables":"m","Typ":"v","Type":"t","TypeAndValue":"t","TypeAndValue.Addressable":"m","TypeAndValue.Assignable":"m","TypeAndValue.HasOk":"m","TypeAndValue.IsBuiltin":"m","TypeAndValue.IsNil":"m","TypeAndValue.IsType":"m","TypeAndValue.IsValue":"m","TypeAndValue.IsVoid":"m","TypeList":"t","TypeList.At":"m","TypeList.Len":"m","TypeList.Types":"m","TypeName":"t","TypeName.IsAlias":"m","TypeName.String":"m","TypeParam":"t","TypeParam.Constraint":"m","TypeParam.Index":"m","TypeParam.Obj":"m","TypeParam.SetConstraint":"m","TypeParam.String":"m","TypeParam.Underlying":"m","TypeParamList":"t","TypeParamList.At":"m","TypeParamList.Len":"m","TypeParamList.TypeParams":"m","TypeString":"f","Uint":"c","Uint16":"c","Uint32":"c","Uint64":"c","Uint8":"c","Uintptr":"c","Unalias":"f","Union":"t","Union.Len":"m","Union.String":"m","Union.Term":"m","Union.Terms":"m","Union.Underlying":"m","Universe":"v","Unsafe":"v","UnsafePointer":"c","UntypedBool":"c","UntypedComplex":"c","UntypedFloat":"c","UntypedInt":"c","UntypedNil":"c","UntypedRune":"c","UntypedString":"c","Var":"t","Var.Anonymous":"m","Var.Embedded":"m","Var.IsField":"m","Var.Kind":"m","Var.Origin":"m","Var.SetKind":"m","Var.String":"m","VarKind":"t","VarKind.String":"m","WriteExpr":"f","WriteSignature":"f","WriteType":"f"}},"go/version":{"path":"go/version","name":"version","symbols":{"Compare":"f","IsValid":"f","Lang":"f"}},"hash":{"path":"hash","name":"hash","symbols":{"Cloner":"t","Hash":"t","Hash32":"t","Hash64":"t","XOF":"t"}},"hash/adler32":{"path":"hash/adler32","name":"adler32","symbols":{"Checksum":"f","New":"f","Size":"c"}},"hash/crc32":{"path":"hash/crc32","name":"crc32","symbols":{"Castagnoli":"c","Checksum":"f","ChecksumIEEE":"f","IEEE":"c","IEEETable":"v","Koopman":"c","MakeTable":"f","New":"f","NewIEEE":"f","Size":"c","Table":"t","Update":"f"}},"hash/crc64":{"path":"hash/crc64","name":"crc64","symbols":{"Checksum":"f","ECMA":"c","ISO":"c","MakeTable":"f","New":"f","Size":"c","Table":"t","Update":"f"}},"hash/fnv":{"path":"hash/fnv","name":"fnv","symbols":{"New128":"f","New128a":"f","New32":"f","New32a":"f","New64":"f","New64a":"f"}},"hash/maphash":{"path":"hash/maphash","name":"maphash","symbols":{"Bytes":"f","Comparable":"f","Hash":"t","Hash.BlockSize":"m","Hash.Clone":"m","Hash.Reset":"m","Hash.Seed":"m","Hash.SetSeed":"m","Hash.Size":"m","Hash.Sum":"m","Hash.Sum64":"m","Hash.Write":"m","Hash.WriteByte":"m","Hash.WriteString":"m","MakeSeed":"f","Seed":"t","String":"f","WriteComparable":"f"}},"html":{"path":"html","name":"html","symbols":{"EscapeString":"f","UnescapeString":"f"}},"html/template":{"path":"html/template","name":"template","symbols":{"CSS":"t","ErrAmbigContext":"c","ErrBadHTML":"c","ErrBranchEnd":"c","ErrEndContext":"c","ErrJSTemplate":"c","ErrNoSuchTemplate":"c","ErrOutputContext":"c","ErrPartialCharset":"c","ErrPartialEscape":"c","ErrPredefinedEscaper":"c","ErrRangeLoopReentry":"c","ErrSlashAmbig":"c","Error":"t","Error.Error":"m","ErrorCode":"t","FuncMap":"t","HTML":"t","HTMLAttr":"t","HTMLEscape":"f","HTMLEscapeString":"f","HTMLEscaper":"f","IsTrue":"f","JS":"t","JSEscape":"f","JSEscapeString":"f","JSEscaper":"f","JSStr":"t","Must":"f","New":"f","OK":"c","ParseFS":"f","ParseFiles":"f","ParseGlob":"f","Srcset":"t","Template":"t","Template.AddParseTree":"m","Template.Clone":"m","Template.DefinedTemplates":"m","Template.Delims":"m","Template.Execute":"m","Template.ExecuteTemplate":"m","Template.Funcs":"m","Template.Lookup":"m","Template.Name":"m","Template.New":"m","Template.Option":"m","Template.Parse":"m","Template.ParseFS":"m","Template.ParseFiles":"m","Template.ParseGlob":"m","Template.Templates":"m","URL":"t","URLQueryEscaper":"f"}},"image":{"path":"image","name":"image","symbols":{"Alpha":"t","Alpha.AlphaAt":"m","Alpha.At":"m","Alpha.Bounds":"m","Alpha.ColorModel":"m","Alpha.Opaque":"m","Alpha.PixOffset":"m","Alpha.RGBA64At":"m","Alpha.Set":"m","Alpha.SetAlpha":"m","Alpha.SetRGBA64":"m","Alpha.SubImage":"m","Alpha16":"t","Alpha16.Alpha16At":"m","Alpha16.At":"m","Alpha16.Bounds":"m","Alpha16.ColorModel":"m","Alpha16.Opaque":"m","Alpha16.PixOffset":"m","Alpha16.RGBA64At":"m","Alpha16.Set":"m","Alpha16.SetAlpha16":"m","Alpha16.SetRGBA64":"m","Alpha16.SubImage":"m","Black":"v","CMYK":"t","CMYK.At":"m","CMYK.Bounds":"m","CMYK.CMYKAt":"m","CMYK.ColorModel":"m","CMYK.Opaque":"m","CMYK.PixOffset":"m","CMYK.RGBA64At":"m","CMYK.Set":"m","CMYK.SetCMYK":"m","CMYK.SetRGBA64":"m","CMYK.SubImage":"m","Config":"t","Decode":"f","DecodeConfig":"f","ErrFormat":"v","Gray":"t","Gray.At":"m","Gray.Bounds":"m","Gray.ColorModel":"m","Gray.GrayAt":"m","Gray.Opaque":"m","Gray.PixOffset":"m","Gray.RGBA64At":"m","Gray.Set":"m","Gray.SetGray":"m","Gray.SetRGBA64":"m","Gray.SubImage":"m","Gray16":"t","Gray16.At":"m","Gray16.Bounds":"m","Gray16.ColorModel":"m","Gray16.Gray16At":"m","Gray16.Opaque":"m","Gray16.PixOffset":"m","Gray16.RGBA64At":"m","Gray16.Set":"m","Gray16.SetGray16":"m","Gray16.SetRGBA64":"m","Gray16.SubImage":"m","Image":"t","NRGBA":"t","NRGBA.At":"m","NRGBA.Bounds":"m","NRGBA.ColorModel":"m","NRGBA.NRGBAAt":"m","NRGBA.Opaque":"m","NRGBA.PixOffset":"m","NRGBA.RGBA64At":"m","NRGBA.Set":"m","NRGBA.SetNRGBA":"m","NRGBA.SetRGBA64":"m","NRGBA.SubImage":"m","NRGBA64":"t","NRGBA64.At":"m","NRGBA64.Bounds":"m","NRGBA64.ColorModel":"m","NRGBA64.NRGBA64At":"m","NRGBA64.Opaque":"m","NRGBA64.PixOffset":"m","NRGBA64.RGBA64At":"m","NRGBA64.Set":"m","NRGBA64.SetNRGBA64":"m","NRGBA64.SetRGBA64":"m","NRGBA64.SubImage":"m","NYCbCrA":"t","NYCbCrA.AOffset":"m","NYCbCrA.At":"m","NYCbCrA.ColorModel":"m","NYCbCrA.NYCbCrAAt":"m","NYCbCrA.Opaque":"m","NYCbCrA.RGBA64At":"m","NYCbCrA.SubImage":"m","NewAlpha":"f","NewAlpha16":"f","NewCMYK":"f","NewGray":"f","NewGray16":"f","NewNRGBA":"f","NewNRGBA64":"f","NewNYCbCrA":"f","NewPaletted":"f","NewRGBA":"f","NewRGBA64":"f","NewUniform":"f","NewYCbCr":"f","Opaque":"v","Paletted":"t","Paletted.At":"m","Paletted.Bounds":"m","Paletted.ColorIndexAt":"m","Paletted.ColorModel":"m","Paletted.Opaque":"m","Paletted.PixOffset":"m","Paletted.RGBA64At":"m","Paletted.Set":"m","Paletted.SetColorIndex":"m","Paletted.SetRGBA64":"m","Paletted.SubImage":"m","PalettedImage":"t","Point":"t","Point.Add":"m","Point.Div":"m","Point.Eq":"m","Point.In":"m","Point.Mod":"m","Point.Mul":"m","Point.String":"m","Point.Sub":"m","Pt":"f","RGBA":"t","RGBA.At":"m","RGBA.Bounds":"m","RGBA.ColorModel":"m","RGBA.Opaque":"m","RGBA.PixOffset":"m","RGBA.RGBA64At":"m","RGBA.RGBAAt":"m","RGBA.Set":"m","RGBA.SetRGBA":"m","RGBA.SetRGBA64":"m","RGBA.SubImage":"m","RGBA64":"t","RGBA64.At":"m","RGBA64.Bounds":"m","RGBA64.ColorModel":"m","RGBA64.Opaque":"m","RGBA64.PixOffset":"m","RGBA64.RGBA64At":"m","RGBA64.Set":"m","RGBA64.SetRGBA64":"m","RGBA64.SubImage":"m","RGBA64Image":"t","Rect":"f","Rectangle":"t","Rectangle.Add":"m","Rectangle.At":"m","Rectangle.Bounds":"m","Rectangle.Canon":"m","Rectangle.ColorModel":"m","Rectangle.Dx":"m","Rectangle.Dy":"m","Rectangle.Empty":"m","Rectangle.Eq":"m","Rectangle.In":"m","Rectangle.Inset":"m","Rectangle.Intersect":"m","Rectangle.Overlaps":"m","Rectangle.RGBA64At":"m","Rectangle.Size":"m","Rectangle.String":"m","Rectangle.Sub":"m","Rectangle.Union":"m","RegisterFormat":"f","Transparent":"v","Uniform":"t","Uniform.At":"m","Uniform.Bounds":"m","Uniform.ColorModel":"m","Uniform.Convert":"m","Uniform.Opaque":"m","Uniform.RGBA":"m","Uniform.RGBA64At":"m","White":"v","YCbCr":"t","YCbCr.At":"m","YCbCr.Bounds":"m","YCbCr.COffset":"m","YCbCr.ColorModel":"m","YCbCr.Opaque":"m","YCbCr.RGBA64At":"m","YCbCr.SubImage":"m","YCbCr.YCbCrAt":"m","YCbCr.YOffset":"m","YCbCrSubsampleRatio":"t","YCbCrSubsampleRatio.String":"m","YCbCrSubsampleRatio410":"c","YCbCrSubsampleRatio411":"c","YCbCrSubsampleRatio420":"c","YCbCrSubsampleRatio422":"c","YCbCrSubsampleRatio440":"c","YCbCrSubsampleRatio444":"c","ZP":"v","ZR":"v"}},"image/color":{"path":"image/color","name":"color","symbols":{"Alpha":"t","Alpha.RGBA":"m","Alpha16":"t","Alpha16.RGBA":"m","Alpha16Model":"v","AlphaModel":"v","Black":"v","CMYK":"t","CMYK.RGBA":"m","CMYKModel":"v","CMYKToRGB":"f","Color":"t","Gray":"t","Gray.RGBA":"m","Gray16":"t","Gray16.RGBA":"m","Gray16Model":"v","GrayModel":"v","Model":"t","ModelFunc":"f","NRGBA":"t","NRGBA.RGBA":"m","NRGBA64":"t","NRGBA64.RGBA":"m","NRGBA64Model":"v","NRGBAModel":"v","NYCbCrA":"t","NYCbCrA.RGBA":"m","NYCbCrAModel":"v","Opaque":"v","Palette":"t","Palette.Convert":"m","Palette.Index":"m","RGBA":"t","RGBA.RGBA":"m","RGBA64":"t","RGBA64.RGBA":"m","RGBA64Model":"v","RGBAModel":"v","RGBToCMYK":"f","RGBToYCbCr":"f","Transparent":"v","White":"v","YCbCr":"t","YCbCr.RGBA":"m","YCbCrModel":"v","YCbCrToRGB":"f"}},"image/color/palette":{"path":"image/color/palette","name":"palette","symbols":{"Plan9":"v","WebSafe":"v"}},"image/draw":{"path":"image/draw","name":"draw","symbols":{"Draw":"f","DrawMask":"f","Drawer":"t","FloydSteinberg":"v","Image":"t","Op":"t","Op.Draw":"m","Over":"c","Quantizer":"t","RGBA64Image":"t","Src":"c"}},"image/gif":{"path":"image/gif","name":"gif","symbols":{"Decode":"f","DecodeAll":"f","DecodeConfig":"f","DisposalBackground":"c","DisposalNone":"c","DisposalPrevious":"c","Encode":"f","EncodeAll":"f","GIF":"t","Options":"t"}},"image/jpeg":{"path":"image/jpeg","name":"jpeg","symbols":{"Decode":"f","DecodeConfig":"f","DefaultQuality":"c","Encode":"f","FormatError":"t","FormatError.Error":"m","Options":"t","Reader":"t","UnsupportedError":"t","UnsupportedError.Error":"m"}},"image/png":{"path":"image/png","name":"png","symbols":{"BestCompression":"c","BestSpeed":"c","CompressionLevel":"t","Decode":"f","DecodeConfig":"f","DefaultCompression":"c","Encode":"f","Encoder":"t","Encoder.Encode":"m","EncoderBuffer":"t","EncoderBufferPool":"t","FormatError":"t","FormatError.Error":"m","NoCompression":"c","UnsupportedError":"t","UnsupportedError.Error":"m"}},"index/suffixarray":{"path":"index/suffixarray","name":"suffixarray","symbols":{"Index":"t","Index.Bytes":"m","Index.FindAllIndex":"m","Index.Lookup":"m","Index.Read":"m","Index.Write":"m","New":"f"}},"io":{"path":"io","name":"io","symbols":{"ByteReader":"t","ByteScanner":"t","ByteWriter":"t","Closer":"t","Copy":"f","CopyBuffer":"f","CopyN":"f","Discard":"v","EOF":"v","ErrClosedPipe":"v","ErrNoProgress":"v","ErrShortBuffer":"v","ErrShortWrite":"v","ErrUnexpectedEOF":"v","LimitReader":"f","LimitedReader":"t","LimitedReader.Read":"m","MultiReader":"f","MultiWriter":"f","NewOffsetWriter":"f","NewSectionReader":"f","NopCloser":"f","OffsetWriter":"t","OffsetWriter.Seek":"m","OffsetWriter.Write":"m","OffsetWriter.WriteAt":"m","Pipe":"f","PipeReader":"t","PipeReader.Close":"m","PipeReader.CloseWithError":"m","PipeReader.Read":"m","PipeWriter":"t","PipeWriter.Close":"m","PipeWriter.CloseWithError":"m","PipeWriter.Write":"m","ReadAll":"f","ReadAtLeast":"f","ReadCloser":"t","ReadFull":"f","ReadSeekCloser":"t","ReadSeeker":"t","ReadWriteCloser":"t","ReadWriteSeeker":"t","ReadWriter":"t","Reader":"t","ReaderAt":"t","ReaderFrom":"t","RuneReader":"t","RuneScanner":"t","SectionReader":"t","SectionReader.Outer":"m","SectionReader.Read":"m","SectionReader.ReadAt":"m","SectionReader.Seek":"m","SectionReader.Size":"m","SeekCurrent":"c","SeekEnd":"c","SeekStart":"c","Seeker":"t","StringWriter":"t","TeeReader":"f","WriteCloser":"t","WriteSeeker":"t","WriteString":"f","Writer":"t","WriterAt":"t","WriterTo":"t"}},"io/fs":{"path":"io/fs","name":"fs","symbols":{"DirEntry":"t","ErrClosed":"v","ErrExist":"v","ErrInvalid":"v","ErrNotExist":"v","ErrPermission":"v","FS":"t","File":"t","FileInfo":"t","FileInfoToDirEntry":"f","FileMode":"t","FileMode.IsDir":"m","FileMode.IsRegular":"m","FileMode.Perm":"m","FileMode.String":"m","FileMode.Type":"m","FormatDirEntry":"f","FormatFileInfo":"f","Glob":"f","GlobFS":"t","Lstat":"f","ModeAppend":"c","ModeCharDevice":"c","ModeDevice":"c","ModeDir":"c","ModeExclusive":"c","ModeIrregular":"c","ModeNamedPipe":"c","ModePerm":"c","ModeSetgid":"c","ModeSetuid":"c","ModeSocket":"c","ModeSticky":"c","ModeSymlink":"c","ModeTemporary":"c","ModeType":"c","PathError":"t","PathError.Error":"m","PathError.Timeout":"m","PathError.Unwrap":"m","ReadDir":"f","ReadDirFS":"t","ReadDirFile":"t","ReadFile":"f","ReadFileFS":"t","ReadLink":"f","ReadLinkFS":"t","SkipAll":"v","SkipDir":"v","Stat":"f","StatFS":"t","Sub":"f","SubFS":"t","ValidPath":"f","WalkDir":"f","WalkDirFunc":"t"}},"io/ioutil":{"path":"io/ioutil","name":"ioutil","symbols":{"Discard":"v","NopCloser":"f","ReadAll":"f","ReadDir":"f","ReadFile":"f","TempDir":"f","TempFile":"f","WriteFile":"f"}},"iter":{"path":"iter","name":"iter","symbols":{"Pull":"f","Pull2":"f","Seq":"t","Seq2":"t"}},"log":{"path":"log","name":"log","symbols":{"Default":"f","Fatal":"f","Fatalf":"f","Fatalln":"f","Flags":"f","LUTC":"c","Ldate":"c","Llongfile":"c","Lmicroseconds":"c","Lmsgprefix":"c","Logger":"t","Logger.Fatal":"m","Logger.Fatalf":"m","Logger.Fatalln":"m","Logger.Flags":"m","Logger.Output":"m","Logger.Panic":"m","Logger.Panicf":"m","Logger.Panicln":"m","Logger.Prefix":"m","Logger.Print":"m","Logger.Printf":"m","Logger.Println":"m","Logger.SetFlags":"m","Logger.SetOutput":"m","Logger.SetPrefix":"m","Logger.Writer":"m","Lshortfile":"c","LstdFlags":"c","Ltime":"c","New":"f","Output":"f","Panic":"f","Panicf":"f","Panicln":"f","Prefix":"f","Print":"f","Printf":"f","Println":"f","SetFlags":"f","SetOutput":"f","SetPrefix":"f","Writer":"f"}},"log/slog":{"path":"log/slog","name":"slog","symbols":{"Any":"f","AnyValue":"f","Attr":"t","Attr.Equal":"m","Attr.String":"m","Bool":"f","BoolValue":"f","Debug":"f","DebugContext":"f","Default":"f","DiscardHandler":"v","Duration":"f","DurationValue":"f","Error":"f","ErrorContext":"f","Float64":"f","Float64Value":"f","Group":"f","GroupAttrs":"f","GroupValue":"f","Handler":"t","HandlerOptions":"t","Info":"f","InfoContext":"f","Int":"f","Int64":"f","Int64Value":"f","IntValue":"f","JSONHandler":"t","JSONHandler.Enabled":"m","JSONHandler.Handle":"m","JSONHandler.WithAttrs":"m","JSONHandler.WithGroup":"m","Kind":"t","Kind.String":"m","KindAny":"c","KindBool":"c","KindDuration":"c","KindFloat64":"c","KindGroup":"c","KindInt64":"c","KindLogValuer":"c","KindString":"c","KindTime":"c","KindUint64":"c","Level":"t","Level.AppendText":"m","Level.Level":"m","Level.MarshalJSON":"m","Level.MarshalText":"m","Level.String":"m","Level.UnmarshalJSON":"m","Level.UnmarshalText":"m","LevelDebug":"c","LevelError":"c","LevelInfo":"c","LevelKey":"c","LevelVar":"t","LevelVar.AppendText":"m","LevelVar.Level":"m","LevelVar.MarshalText":"m","LevelVar.Set":"m","LevelVar.String":"m","LevelVar.UnmarshalText":"m","LevelWarn":"c","Leveler":"t","Log":"f","LogAttrs":"f","LogValuer":"t","Logger":"t","Logger.Debug":"m","Logger.DebugContext":"m","Logger.Enabled":"m","Logger.Error":"m","Logger.ErrorContext":"m","Logger.Handler":"m","Logger.Info":"m","Logger.InfoContext":"m","Logger.Log":"m","Logger.LogAttrs":"m","Logger.Warn":"m","Logger.WarnContext":"m","Logger.With":"m","Logger.WithGroup":"m","MessageKey":"c","New":"f","NewJSONHandler":"f","NewLogLogger":"f","NewRecord":"f","NewTextHandler":"f","Record":"t","Record.Add":"m","Record.AddAttrs":"m","Record.Attrs":"m","Record.Clone":"m","Record.NumAttrs":"m","Record.Source":"m","SetDefault":"f","SetLogLoggerLevel":"f","Source":"t","SourceKey":"c","String":"f","StringValue":"f","TextHandler":"t","TextHandler.Enabled":"m","TextHandler.Handle":"m","TextHandler.WithAttrs":"m","TextHandler.WithGroup":"m","Time":"f","TimeKey":"c","TimeValue":"f","Uint64":"f","Uint64Value":"f","Value":"t","Value.Any":"m","Value.Bool":"m","Value.Duration":"m","Value.Equal":"m","Value.Float64":"m","Value.Group":"m","Value.Int64":"m","Value.Kind":"m","Value.LogValuer":"m","Value.Resolve":"m","Value.String":"m","Value.Time":"m","Value.Uint64":"m","Warn":"f","WarnContext":"f","With":"f"}},"log/syslog":{"path":"log/syslog","name":"syslog","symbols":{"Dial":"f","LOG_ALERT":"c","LOG_AUTH":"c","LOG_AUTHPRIV":"c","LOG_CRIT":"c","LOG_CRON":"c","LOG_DAEMON":"c","LOG_DEBUG":"c","LOG_EMERG":"c","LOG_ERR":"c","LOG_FTP":"c","LOG_INFO":"c","LOG_KERN":"c","LOG_LOCAL0":"c","LOG_LOCAL1":"c","LOG_LOCAL2":"c","LOG_LOCAL3":"c","LOG_LOCAL4":"c","LOG_LOCAL5":"c","LOG_LOCAL6":"c","LOG_LOCAL7":"c","LOG_LPR":"c","LOG_MAIL":"c","LOG_NEWS":"c","LOG_NOTICE":"c","LOG_SYSLOG":"c","LOG_USER":"c","LOG_UUCP":"c","LOG_WARNING":"c","New":"f","NewLogger":"f","Priority":"t","Writer":"t","Writer.Alert":"m","Writer.Close":"m","Writer.Crit":"m","Writer.Debug":"m","Writer.Emerg":"m","Writer.Err":"m","Writer.Info":"m","Writer.Notice":"m","Writer.Warning":"m","Writer.Write":"m"}},"maps":{"path":"maps","name":"maps","symbols":{"All":"f","Clone":"f","Collect":"f","Copy":"f","DeleteFunc":"f","Equal":"f","EqualFunc":"f","Insert":"f","Keys":"f","Values":"f"}},"math":{"path":"math","name":"math","symbols":{"Abs":"f","Acos":"f","Acosh":"f","Asin":"f","Asinh":"f","Atan":"f","Atan2":"f","Atanh":"f","Cbrt":"f","Ceil":"f","Copysign":"f","Cos":"f","Cosh":"f","Dim":"f","E":"c","Erf":"f","Erfc":"f","Erfcinv":"f","Erfinv":"f","Exp":"f","Exp2":"f","Expm1":"f","FMA":"f","Float32bits":"f","Float32frombits":"f","Float64bits":"f","Float64frombits":"f","Floor":"f","Frexp":"f","Gamma":"f","Hypot":"f","Ilogb":"f","Inf":"f","IsInf":"f","IsNaN":"f","J0":"f","J1":"f","Jn":"f","Ldexp":"f","Lgamma":"f","Ln10":"c","Ln2":"c","Log":"f","Log10":"f","Log10E":"c","Log1p":"f","Log2":"f","Log2E":"c","Logb":"f","Max":"f","MaxFloat32":"c","MaxFloat64":"c","MaxInt":"c","MaxInt16":"c","MaxInt32":"c","MaxInt64":"c","MaxInt8":"c","MaxUint":"c","MaxUint16":"c","MaxUint32":"c","MaxUint64":"c","MaxUint8":"c","Min":"f","MinInt":"c","MinInt16":"c","MinInt32":"c","MinInt64":"c","MinInt8":"c","Mod":"f","Modf":"f","NaN":"f","Nextafter":"f","Nextafter32":"f","Phi":"c","Pi":"c","Pow":"f","Pow10":"f","Remainder":"f","Round":"f","RoundToEven":"f","Signbit":"f","Sin":"f","Sincos":"f","Sinh":"f","SmallestNonzeroFloat32":"c","SmallestNonzeroFloat64":"c","Sqrt":"f","Sqrt2":"c","SqrtE":"c","SqrtPhi":"c","SqrtPi":"c","Tan":"f","Tanh":"f","Trunc":"f","Y0":"f","Y1":"f","Yn":"f"}},"math/big":{"path":"math/big","name":"big","symbols":{"Above":"c","Accuracy":"t","Accuracy.String":"m","AwayFromZero":"c","Below":"c","ErrNaN":"t","ErrNaN.Error":"m","Exact":"c","Float":"t","Float.Abs":"m","Float.Acc":"m","Float.Add":"m","Float.Append":"m","Float.AppendText":"m","Float.Cmp":"m","Float.Copy":"m","Float.Float32":"m","Float.Float64":"m","Float.Format":"m","Float.GobDecode":"m","Float.GobEncode":"m","Float.Int":"m","Float.Int64":"m","Float.IsInf":"m","Float.IsInt":"m","Float.MantExp":"m","Float.MarshalText":"m","Float.MinPrec":"m","Float.Mode":"m","Float.Mul":"m","Float.Neg":"m","Float.Parse":"m","Float.Prec":"m","Float.Quo":"m","Float.Rat":"m","Float.Scan":"m","Float.Set":"m","Float.SetFloat64":"m","Float.SetInf":"m","Float.SetInt":"m","Float.SetInt64":"m","Float.SetMantExp":"m","Float.SetMode":"m","Float.SetPrec":"m","Float.SetRat":"m","Float.SetString":"m","Float.SetUint64":"m","Float.Sign":"m","Float.Signbit":"m","Float.Sqrt":"m","Float.String":"m","Float.Sub":"m","Float.Text":"m","Float.Uint64":"m","Float.UnmarshalText":"m","Int":"t","Int.Abs":"m","Int.Add":"m","Int.And":"m","Int.AndNot":"m","Int.Append":"m","Int.AppendText":"m","Int.Binomial":"m","Int.Bit":"m","Int.BitLen":"m","Int.Bits":"m","Int.Bytes":"m","Int.Cmp":"m","Int.CmpAbs":"m","Int.Div":"m","Int.DivMod":"m","Int.Exp":"m","Int.FillBytes":"m","Int.Float64":"m","Int.Format":"m","Int.GCD":"m","Int.GobDecode":"m","Int.GobEncode":"m","Int.Int64":"m","Int.IsInt64":"m","Int.IsUint64":"m","Int.Lsh":"m","Int.MarshalJSON":"m","Int.MarshalText":"m","Int.Mod":"m","Int.ModInverse":"m","Int.ModSqrt":"m","Int.Mul":"m","Int.MulRange":"m","Int.Neg":"m","Int.Not":"m","Int.Or":"m","Int.ProbablyPrime":"m","Int.Quo":"m","Int.QuoRem":"m","Int.Rand":"m","Int.Rem":"m","Int.Rsh":"m","Int.Scan":"m","Int.Set":"m","Int.SetBit":"m","Int.SetBits":"m","Int.SetBytes":"m","Int.SetInt64":"m","Int.SetString":"m","Int.SetUint64":"m","Int.Sign":"m","Int.Sqrt":"m","Int.String":"m","Int.Sub":"m","Int.Text":"m","Int.TrailingZeroBits":"m","Int.Uint64":"m","Int.UnmarshalJSON":"m","Int.UnmarshalText":"m","Int.Xor":"m","Jacobi":"f","MaxBase":"c","MaxExp":"c","MaxPrec":"c","MinExp":"c","NewFloat":"f","NewInt":"f","NewRat":"f","ParseFloat":"f","Rat":"t","Rat.Abs":"m","Rat.Add":"m","Rat.AppendText":"m","Rat.Cmp":"m","Rat.Denom":"m","Rat.Float32":"m","Rat.Float64":"m","Rat.FloatPrec":"m","Rat.FloatString":"m","Rat.GobDecode":"m","Rat.GobEncode":"m","Rat.Inv":"m","Rat.IsInt":"m","Rat.MarshalText":"m","Rat.Mul":"m","Rat.Neg":"m","Rat.Num":"m","Rat.Quo":"m","Rat.RatString":"m","Rat.Scan":"m","Rat.Set":"m","Rat.SetFloat64":"m","Rat.SetFrac":"m","Rat.SetFrac64":"m","Rat.SetInt":"m","Rat.SetInt64":"m","Rat.SetString":"m","Rat.SetUint64":"m","Rat.Sign":"m","Rat.String":"m","Rat.Sub":"m","Rat.UnmarshalText":"m","RoundingMode":"t","RoundingMode.String":"m","ToNearestAway":"c","ToNearestEven":"c","ToNegativeInf":"c","ToPositiveInf":"c","ToZero":"c","Word":"t"}},"math/bits":{"path":"math/bits","name":"bits","symbols":{"Add":"f","Add32":"f","Add64":"f","Div":"f","Div32":"f","Div64":"f","LeadingZeros":"f","LeadingZeros16":"f","LeadingZeros32":"f","LeadingZeros64":"f","LeadingZeros8":"f","Len":"f","Len16":"f","Len32":"f","Len64":"f","Len8":"f","Mul":"f","Mul32":"f","Mul64":"f","OnesCount":"f","OnesCount16":"f","OnesCount32":"f","OnesCount64":"f","OnesCount8":"f","Rem":"f","Rem32":"f","Rem64":"f","Reverse":"f","Reverse16":"f","Reverse32":"f","Reverse64":"f","Reverse8":"f","ReverseBytes":"f","ReverseBytes16":"f","ReverseBytes32":"f","ReverseBytes64":"f","RotateLeft":"f","RotateLeft16":"f","RotateLeft32":"f","RotateLeft64":"f","RotateLeft8":"f","Sub":"f","Sub32":"f","Sub64":"f","TrailingZeros":"f","TrailingZeros16":"f","TrailingZeros32":"f","TrailingZeros64":"f","TrailingZeros8":"f","UintSize":"c"}},"math/cmplx":{"path":"math/cmplx","name":"cmplx","symbols":{"Abs":"f","Acos":"f","Acosh":"f","Asin":"f","Asinh":"f","Atan":"f","Atanh":"f","Conj":"f","Cos":"f","Cosh":"f","Cot":"f","Exp":"f","Inf":"f","IsInf":"f","IsNaN":"f","Log":"f","Log10":"f","NaN":"f","Phase":"f","Polar":"f","Pow":"f","Rect":"f","Sin":"f","Sinh":"f","Sqrt":"f","Tan":"f","Tanh":"f"}},"math/rand":{"path":"math/rand","name":"rand","symbols":{"ExpFloat64":"f","Float32":"f","Float64":"f","Int":"f","Int31":"f","Int31n":"f","Int63":"f","Int63n":"f","Intn":"f","New":"f","NewSource":"f","NewZipf":"f","NormFloat64":"f","Perm":"f","Rand":"t","Rand.ExpFloat64":"m","Rand.Float32":"m","Rand.Float64":"m","Rand.Int":"m","Rand.Int31":"m","Rand.Int31n":"m","Rand.Int63":"m","Rand.Int63n":"m","Rand.Intn":"m","Rand.NormFloat64":"m","Rand.Perm":"m","Rand.Read":"m","Rand.Seed":"m","Rand.Shuffle":"m","Rand.Uint32":"m","Rand.Uint64":"m","Read":"f","Seed":"f","Shuffle":"f","Source":"t","Source64":"t","Uint32":"f","Uint64":"f","Zipf":"t","Zipf.Uint64":"m"}},"math/rand/v2":{"path":"math/rand/v2","name":"rand","symbols":{"ChaCha8":"t","ChaCha8.AppendBinary":"m","ChaCha8.MarshalBinary":"m","ChaCha8.Read":"m","ChaCha8.Seed":"m","ChaCha8.Uint64":"m","ChaCha8.UnmarshalBinary":"m","ExpFloat64":"f","Float32":"f","Float64":"f","Int":"f","Int32":"f","Int32N":"f","Int64":"f","Int64N":"f","IntN":"f","N":"f","New":"f","NewChaCha8":"f","NewPCG":"f","NewZipf":"f","NormFloat64":"f","PCG":"t","PCG.AppendBinary":"m","PCG.MarshalBinary":"m","PCG.Seed":"m","PCG.Uint64":"m","PCG.UnmarshalBinary":"m","Perm":"f","Rand":"t","Rand.ExpFloat64":"m","Rand.Float32":"m","Rand.Float64":"m","Rand.Int":"m","Rand.Int32":"m","Rand.Int32N":"m","Rand.Int64":"m","Rand.Int64N":"m","Rand.IntN":"m","Rand.NormFloat64":"m","Rand.Perm":"m","Rand.Shuffle":"m","Rand.Uint":"m","Rand.Uint32":"m","Rand.Uint32N":"m","Rand.Uint64":"m","Rand.Uint64N":"m","Rand.UintN":"m","Shuffle":"f","Source":"t","Uint":"f","Uint32":"f","Uint32N":"f","Uint64":"f","Uint64N":"f","UintN":"f","Zipf":"t","Zipf.Uint64":"m"}},"mime":{"path":"mime","name":"mime","symbols":{"AddExtensionType":"f","BEncoding":"c","ErrInvalidMediaParameter":"v","ExtensionsByType":"f","FormatMediaType":"f","ParseMediaType":"f","QEncoding":"c","TypeByExtension":"f","WordDecoder":"t","WordDecoder.Decode":"m","WordDecoder.DecodeHeader":"m","WordEncoder":"t","WordEncoder.Encode":"m"}},"mime/multipart":{"path":"mime/multipart","name":"multipart","symbols":{"ErrMessageTooLarge":"v","File":"t","FileContentDisposition":"f","FileHeader":"t","FileHeader.Open":"m","Form":"t","Form.RemoveAll":"m","NewReader":"f","NewWriter":"f","Part":"t","Part.Close":"m","Part.FileName":"m","Part.FormName":"m","Part.Read":"m","Reader":"t","Reader.NextPart":"m","Reader.NextRawPart":"m","Reader.ReadForm":"m","Writer":"t","Writer.Boundary":"m","Writer.Close":"m","Writer.CreateFormField":"m","Writer.CreateFormFile":"m","Writer.CreatePart":"m","Writer.FormDataContentType":"m","Writer.SetBoundary":"m","Writer.WriteField":"m"}},"mime/quotedprintable":{"path":"mime/quotedprintable","name":"quotedprintable","symbols":{"NewReader":"f","NewWriter":"f","Reader":"t","Reader.Read":"m","Writer":"t","Writer.Close":"m","Writer.Write":"m"}},"net":{"path":"net","name":"net","symbols":{"Addr":"t","AddrError":"t","AddrError.Error":"m","AddrError.Temporary":"m","AddrError.Timeout":"m","Buffers":"t","Buffers.Read":"m","Buffers.WriteTo":"m","CIDRMask":"f","Conn":"t","DNSConfigError":"t","DNSConfigError.Error":"m","DNSConfigError.Temporary":"m","DNSConfigError.Timeout":"m","DNSConfigError.Unwrap":"m","DNSError":"t","DNSError.Error":"m","DNSError.Temporary":"m","DNSError.Timeout":"m","DNSError.Unwrap":"m","DefaultResolver":"v","Dial":"f","DialIP":"f","DialTCP":"f","DialTimeout":"f","DialUDP":"f","DialUnix":"f","Dialer":"t","Dialer.Dial":"m","Dialer.DialContext":"m","Dialer.MultipathTCP":"m","Dialer.SetMultipathTCP":"m","ErrClosed":"v","ErrWriteToConnected":"v","Error":"t","FileConn":"f","FileListener":"f","FilePacketConn":"f","FlagBroadcast":"c","FlagLoopback":"c","FlagMulticast":"c","FlagPointToPoint":"c","FlagRunning":"c","FlagUp":"c","Flags":"t","Flags.String":"m","HardwareAddr":"t","HardwareAddr.String":"m","IP":"t","IP.AppendText":"m","IP.DefaultMask":"m","IP.Equal":"m","IP.IsGlobalUnicast":"m","IP.IsInterfaceLocalMulticast":"m","IP.IsLinkLocalMulticast":"m","IP.IsLinkLocalUnicast":"m","IP.IsLoopback":"m","IP.IsMulticast":"m","IP.IsPrivate":"m","IP.IsUnspecified":"m","IP.MarshalText":"m","IP.Mask":"m","IP.String":"m","IP.To16":"m","IP.To4":"m","IP.UnmarshalText":"m","IPAddr":"t","IPAddr.Network":"m","IPAddr.String":"m","IPConn":"t","IPConn.ReadFrom":"m","IPConn.ReadFromIP":"m","IPConn.ReadMsgIP":"m","IPConn.SyscallConn":"m","IPConn.WriteMsgIP":"m","IPConn.WriteTo":"m","IPConn.WriteToIP":"m","IPMask":"t","IPMask.Size":"m","IPMask.String":"m","IPNet":"t","IPNet.Contains":"m","IPNet.Network":"m","IPNet.String":"m","IPv4":"f","IPv4Mask":"f","IPv4allrouter":"v","IPv4allsys":"v","IPv4bcast":"v","IPv4len":"c","IPv4zero":"v","IPv6interfacelocalallnodes":"v","IPv6len":"c","IPv6linklocalallnodes":"v","IPv6linklocalallrouters":"v","IPv6loopback":"v","IPv6unspecified":"v","IPv6zero":"v","Interface":"t","Interface.Addrs":"m","Interface.MulticastAddrs":"m","InterfaceAddrs":"f","InterfaceByIndex":"f","InterfaceByName":"f","Interfaces":"f","InvalidAddrError":"t","InvalidAddrError.Error":"m","InvalidAddrError.Temporary":"m","InvalidAddrError.Timeout":"m","JoinHostPort":"f","KeepAliveConfig":"t","Listen":"f","ListenConfig":"t","ListenConfig.Listen":"m","ListenConfig.ListenPacket":"m","ListenConfig.MultipathTCP":"m","ListenConfig.SetMultipathTCP":"m","ListenIP":"f","ListenMulticastUDP":"f","ListenPacket":"f","ListenTCP":"f","ListenUDP":"f","ListenUnix":"f","ListenUnixgram":"f","Listener":"t","LookupAddr":"f","LookupCNAME":"f","LookupHost":"f","LookupIP":"f","LookupMX":"f","LookupNS":"f","LookupPort":"f","LookupSRV":"f","LookupTXT":"f","MX":"t","NS":"t","OpError":"t","OpError.Error":"m","OpError.Temporary":"m","OpError.Timeout":"m","OpError.Unwrap":"m","PacketConn":"t","ParseCIDR":"f","ParseError":"t","ParseError.Error":"m","ParseError.Temporary":"m","ParseError.Timeout":"m","ParseIP":"f","ParseMAC":"f","Pipe":"f","ResolveIPAddr":"f","ResolveTCPAddr":"f","ResolveUDPAddr":"f","ResolveUnixAddr":"f","Resolver":"t","Resolver.LookupAddr":"m","Resolver.LookupCNAME":"m","Resolver.LookupHost":"m","Resolver.LookupIP":"m","Resolver.LookupIPAddr":"m","Resolver.LookupMX":"m","Resolver.LookupNS":"m","Resolver.LookupNetIP":"m","Resolver.LookupPort":"m","Resolver.LookupSRV":"m","Resolver.LookupTXT":"m","SRV":"t","SplitHostPort":"f","TCPAddr":"t","TCPAddr.AddrPort":"m","TCPAddr.Network":"m","TCPAddr.String":"m","TCPAddrFromAddrPort":"f","TCPConn":"t","TCPConn.CloseRead":"m","TCPConn.CloseWrite":"m","TCPConn.MultipathTCP":"m","TCPConn.ReadFrom":"m","TCPConn.SetKeepAlive":"m","TCPConn.SetKeepAliveConfig":"m","TCPConn.SetKeepAlivePeriod":"m","TCPConn.SetLinger":"m","TCPConn.SetNoDelay":"m","TCPConn.SyscallConn":"m","TCPConn.WriteTo":"m","TCPListener":"t","TCPListener.Accept":"m","TCPListener.AcceptTCP":"m","TCPListener.Addr":"m","TCPListener.Close":"m","TCPListener.File":"m","TCPListener.SetDeadline":"m","TCPListener.SyscallConn":"m","UDPAddr":"t","UDPAddr.AddrPort":"m","UDPAddr.Network":"m","UDPAddr.String":"m","UDPAddrFromAddrPort":"f","UDPConn":"t","UDPConn.ReadFrom":"m","UDPConn.ReadFromUDP":"m","UDPConn.ReadFromUDPAddrPort":"m","UDPConn.ReadMsgUDP":"m","UDPConn.ReadMsgUDPAddrPort":"m","UDPConn.SyscallConn":"m","UDPConn.WriteMsgUDP":"m","UDPConn.WriteMsgUDPAddrPort":"m","UDPConn.WriteTo":"m","UDPConn.WriteToUDP":"m","UDPConn.WriteToUDPAddrPort":"m","UnixAddr":"t","UnixAddr.Network":"m","UnixAddr.String":"m","UnixConn":"t","UnixConn.CloseRead":"m","UnixConn.CloseWrite":"m","UnixConn.ReadFrom":"m","UnixConn.ReadFromUnix":"m","UnixConn.ReadMsgUnix":"m","UnixConn.SyscallConn":"m","UnixConn.WriteMsgUnix":"m","UnixConn.WriteTo":"m","UnixConn.WriteToUnix":"m","UnixListener":"t","UnixListener.Accept":"m","UnixListener.AcceptUnix":"m","UnixListener.Addr":"m","UnixListener.Close":"m","UnixListener.File":"m","UnixListener.SetDeadline":"m","UnixListener.SetUnlinkOnClose":"m","UnixListener.SyscallConn":"m","UnknownNetworkError":"t","UnknownNetworkError.Error":"m","UnknownNetworkError.Temporary":"m","UnknownNetworkError.Timeout":"m"}},"net/http":{"path":"net/http","name":"http","symbols":{"AllowQuerySemicolons":"f","CanonicalHeaderKey":"f","Client":"t","Client.CloseIdleConnections":"m","Client.Do":"m","Client.Get":"m","Client.Head":"m","Client.Post":"m","Client.PostForm":"m","CloseNotifier":"t","ConnState":"t","ConnState.String":"m","Cookie":"t","Cookie.String":"m","Cookie.Valid":"m","CookieJar":"t","CrossOriginProtection":"t","CrossOriginProtection.AddInsecureBypassPattern":"m","CrossOriginProtection.AddTrustedOrigin":"m","CrossOriginProtection.Check":"m","CrossOriginProtection.Handler":"m","CrossOriginProtection.SetDenyHandler":"m","DefaultClient":"v","DefaultMaxHeaderBytes":"c","DefaultMaxIdleConnsPerHost":"c","DefaultServeMux":"v","DefaultTransport":"v","DetectContentType":"f","Dir":"t","Dir.Open":"m","ErrAbortHandler":"v","ErrBodyNotAllowed":"v","ErrBodyReadAfterClose":"v","ErrContentLength":"v","ErrHandlerTimeout":"v","ErrHeaderTooLong":"v","ErrHijacked":"v","ErrLineTooLong":"v","ErrMissingBoundary":"v","ErrMissingContentLength":"v","ErrMissingFile":"v","ErrNoCookie":"v","ErrNoLocation":"v","ErrNotMultipart":"v","ErrNotSupported":"v","ErrSchemeMismatch":"v","ErrServerClosed":"v","ErrShortBody":"v","ErrSkipAltProtocol":"v","ErrUnexpectedTrailer":"v","ErrUseLastResponse":"v","ErrWriteAfterFlush":"v","Error":"f","FS":"f","File":"t","FileServer":"f","FileServerFS":"f","FileSystem":"t","Flusher":"t","Get":"f","HTTP2Config":"t","Handle":"f","HandleFunc":"f","Handler":"t","HandlerFunc":"t","HandlerFunc.ServeHTTP":"m","Head":"f","Header":"t","Header.Add":"m","Header.Clone":"m","Header.Del":"m","Header.Get":"m","Header.Set":"m","Header.Values":"m","Header.Write":"m","Header.WriteSubset":"m","Hijacker":"t","ListenAndServe":"f","ListenAndServeTLS":"f","LocalAddrContextKey":"v","MaxBytesError":"t","MaxBytesError.Error":"m","MaxBytesHandler":"f","MaxBytesReader":"f","MethodConnect":"c","MethodDelete":"c","MethodGet":"c","MethodHead":"c","MethodOptions":"c","MethodPatch":"c","MethodPost":"c","MethodPut":"c","MethodTrace":"c","NewCrossOriginProtection":"f","NewFileTransport":"f","NewFileTransportFS":"f","NewRequest":"f","NewRequestWithContext":"f","NewResponseController":"f","NewServeMux":"f","NoBody":"v","NotFound":"f","NotFoundHandler":"f","ParseCookie":"f","ParseHTTPVersion":"f","ParseSetCookie":"f","ParseTime":"f","Post":"f","PostForm":"f","ProtocolError":"t","ProtocolError.Error":"m","ProtocolError.Is":"m","Protocols":"t","Protocols.HTTP1":"m","Protocols.HTTP2":"m","Protocols.SetHTTP1":"m","Protocols.SetHTTP2":"m","Protocols.SetUnencryptedHTTP2":"m","Protocols.String":"m","Protocols.UnencryptedHTTP2":"m","ProxyFromEnvironment":"f","ProxyURL":"f","PushOptions":"t","Pusher":"t","ReadRequest":"f","ReadResponse":"f","Redirect":"f","RedirectHandler":"f","Request":"t","Request.AddCookie":"m","Request.BasicAuth":"m","Request.Clone":"m","Request.Context":"m","Request.Cookie":"m","Request.Cookies":"m","Request.CookiesNamed":"m","Request.FormFile":"m","Request.FormValue":"m","Request.MultipartReader":"m","Request.ParseForm":"m","Request.ParseMultipartForm":"m","Request.PathValue":"m","Request.PostFormValue":"m","Request.ProtoAtLeast":"m","Request.Referer":"m","Request.SetBasicAuth":"m","Request.SetPathValue":"m","Request.UserAgent":"m","Request.WithContext":"m","Request.Write":"m","Request.WriteProxy":"m","Response":"t","Response.Cookies":"m","Response.Location":"m","Response.ProtoAtLeast":"m","Response.Write":"m","ResponseController":"t","ResponseController.EnableFullDuplex":"m","ResponseController.Flush":"m","ResponseController.Hijack":"m","ResponseController.SetReadDeadline":"m","ResponseController.SetWriteDeadline":"m","ResponseWriter":"t","RoundTripper":"t","SameSite":"t","SameSiteDefaultMode":"c","SameSiteLaxMode":"c","SameSiteNoneMode":"c","SameSiteStrictMode":"c","Serve":"f","ServeContent":"f","ServeFile":"f","ServeFileFS":"f","ServeMux":"t","ServeMux.Handle":"m","ServeMux.HandleFunc":"m","ServeMux.Handler":"m","ServeMux.ServeHTTP":"m","ServeTLS":"f","Server":"t","Server.Close":"m","Server.ListenAndServe":"m","Server.ListenAndServeTLS":"m","Server.RegisterOnShutdown":"m","Server.Serve":"m","Server.ServeTLS":"m","Server.SetKeepAlivesEnabled":"m","Server.Shutdown":"m","ServerContextKey":"v","SetCookie":"f","StateActive":"c","StateClosed":"c","StateHijacked":"c","StateIdle":"c","StateNew":"c","StatusAccepted":"c","StatusAlreadyReported":"c","StatusBadGateway":"c","StatusBadRequest":"c","StatusConflict":"c","StatusContinue":"c","StatusCreated":"c","StatusEarlyHints":"c","StatusExpectationFailed":"c","StatusFailedDependency":"c","StatusForbidden":"c","StatusFound":"c","StatusGatewayTimeout":"c","StatusGone":"c","StatusHTTPVersionNotSupported":"c","StatusIMUsed":"c","StatusInsufficientStorage":"c","StatusInternalServerError":"c","StatusLengthRequired":"c","StatusLocked":"c","StatusLoopDetected":"c","StatusMethodNotAllowed":"c","StatusMisdirectedRequest":"c","StatusMovedPermanently":"c","StatusMultiStatus":"c","StatusMultipleChoices":"c","StatusNetworkAuthenticationRequired":"c","StatusNoContent":"c","StatusNonAuthoritativeInfo":"c","StatusNotAcceptable":"c","StatusNotExtended":"c","StatusNotFound":"c","StatusNotImplemented":"c","StatusNotModified":"c","StatusOK":"c","StatusPartialContent":"c","StatusPaymentRequired":"c","StatusPermanentRedirect":"c","StatusPreconditionFailed":"c","StatusPreconditionRequired":"c","StatusProcessing":"c","StatusProxyAuthRequired":"c","StatusRequestEntityTooLarge":"c","StatusRequestHeaderFieldsTooLarge":"c","StatusRequestTimeout":"c","StatusRequestURITooLong":"c","StatusRequestedRangeNotSatisfiable":"c","StatusResetContent":"c","StatusSeeOther":"c","StatusServiceUnavailable":"c","StatusSwitchingProtocols":"c","StatusTeapot":"c","StatusTemporaryRedirect":"c","StatusText":"f","StatusTooEarly":"c","StatusTooManyRequests":"c","StatusUnauthorized":"c","StatusUnavailableForLegalReasons":"c","StatusUnprocessableEntity":"c","StatusUnsupportedMediaType":"c","StatusUpgradeRequired":"c","StatusUseProxy":"c","StatusVariantAlsoNegotiates":"c","StripPrefix":"f","TimeFormat":"c","TimeoutHandler":"f","TrailerPrefix":"c","Transport":"t","Transport.CancelRequest":"m","Transport.Clone":"m","Transport.CloseIdleConnections":"m","Transport.RegisterProtocol":"m","Transport.RoundTrip":"m"}},"net/http/cgi":{"path":"net/http/cgi","name":"cgi","symbols":{"Handler":"t","Handler.ServeHTTP":"m","Request":"f","RequestFromMap":"f","Serve":"f"}},"net/http/cookiejar":{"path":"net/http/cookiejar","name":"cookiejar","symbols":{"Jar":"t","Jar.Cookies":"m","Jar.SetCookies":"m","New":"f","Options":"t","PublicSuffixList":"t"}},"net/http/fcgi":{"path":"net/http/fcgi","name":"fcgi","symbols":{"ErrConnClosed":"v","ErrRequestAborted":"v","ProcessEnv":"f","Serve":"f"}},"net/http/httptest":{"path":"net/http/httptest","name":"httptest","symbols":{"DefaultRemoteAddr":"c","NewRecorder":"f","NewRequest":"f","NewRequestWithContext":"f","NewServer":"f","NewTLSServer":"f","NewUnstartedServer":"f","ResponseRecorder":"t","ResponseRecorder.Flush":"m","ResponseRecorder.Header":"m","ResponseRecorder.Result":"m","ResponseRecorder.Write":"m","ResponseRecorder.WriteHeader":"m","ResponseRecorder.WriteString":"m","Server":"t","Server.Certificate":"m","Server.Client":"m","Server.Close":"m","Server.CloseClientConnections":"m","Server.Start":"m","Server.StartTLS":"m"}},"net/http/httptrace":{"path":"net/http/httptrace","name":"httptrace","symbols":{"ClientTrace":"t","ContextClientTrace":"f","DNSDoneInfo":"t","DNSStartInfo":"t","GotConnInfo":"t","WithClientTrace":"f","WroteRequestInfo":"t"}},"net/http/httputil":{"path":"net/http/httputil","name":"httputil","symbols":{"BufferPool":"t","ClientConn":"t","ClientConn.Close":"m","ClientConn.Do":"m","ClientConn.Hijack":"m","ClientConn.Pending":"m","ClientConn.Read":"m","ClientConn.Write":"m","DumpRequest":"f","DumpRequestOut":"f","DumpResponse":"f","ErrClosed":"v","ErrLineTooLong":"v","ErrPersistEOF":"v","ErrPipeline":"v","NewChunkedReader":"f","NewChunkedWriter":"f","NewClientConn":"f","NewProxyClientConn":"f","NewServerConn":"f","NewSingleHostReverseProxy":"f","ProxyRequest":"t","ProxyRequest.SetURL":"m","ProxyRequest.SetXForwarded":"m","ReverseProxy":"t","ReverseProxy.ServeHTTP":"m","ServerConn":"t","ServerConn.Close":"m","ServerConn.Hijack":"m","ServerConn.Pending":"m","ServerConn.Read":"m","ServerConn.Write":"m"}},"net/http/pprof":{"path":"net/http/pprof","name":"pprof","symbols":{"Cmdline":"f","Handler":"f","Index":"f","Profile":"f","Symbol":"f","Trace":"f"}},"net/mail":{"path":"net/mail","name":"mail","symbols":{"Address":"t","Address.String":"m","AddressParser":"t","AddressParser.Parse":"m","AddressParser.ParseList":"m","ErrHeaderNotPresent":"v","Header":"t","Header.AddressList":"m","Header.Date":"m","Header.Get":"m","Message":"t","ParseAddress":"f","ParseAddressList":"f","ParseDate":"f","ReadMessage":"f"}},"net/netip":{"path":"net/netip","name":"netip","symbols":{"Addr":"t","Addr.AppendBinary":"m","Addr.AppendText":"m","Addr.AppendTo":"m","Addr.As16":"m","Addr.As4":"m","Addr.AsSlice":"m","Addr.BitLen":"m","Addr.Compare":"m","Addr.Is4":"m","Addr.Is4In6":"m","Addr.Is6":"m","Addr.IsGlobalUnicast":"m","Addr.IsInterfaceLocalMulticast":"m","Addr.IsLinkLocalMulticast":"m","Addr.IsLinkLocalUnicast":"m","Addr.IsLoopback":"m","Addr.IsMulticast":"m","Addr.IsPrivate":"m","Addr.IsUnspecified":"m","Addr.IsValid":"m","Addr.Less":"m","Addr.MarshalBinary":"m","Addr.MarshalText":"m","Addr.Next":"m","Addr.Prefix":"m","Addr.Prev":"m","Addr.String":"m","Addr.StringExpanded":"m","Addr.Unmap":"m","Addr.UnmarshalBinary":"m","Addr.UnmarshalText":"m","Addr.WithZone":"m","Addr.Zone":"m","AddrFrom16":"f","AddrFrom4":"f","AddrFromSlice":"f","AddrPort":"t","AddrPort.Addr":"m","AddrPort.AppendBinary":"m","AddrPort.AppendText":"m","AddrPort.AppendTo":"m","AddrPort.Compare":"m","AddrPort.IsValid":"m","AddrPort.MarshalBinary":"m","AddrPort.MarshalText":"m","AddrPort.Port":"m","AddrPort.String":"m","AddrPort.UnmarshalBinary":"m","AddrPort.UnmarshalText":"m","AddrPortFrom":"f","IPv4Unspecified":"f","IPv6LinkLocalAllNodes":"f","IPv6LinkLocalAllRouters":"f","IPv6Loopback":"f","IPv6Unspecified":"f","MustParseAddr":"f","MustParseAddrPort":"f","MustParsePrefix":"f","ParseAddr":"f","ParseAddrPort":"f","ParsePrefix":"f","Prefix":"t","Prefix.Addr":"m","Prefix.AppendBinary":"m","Prefix.AppendText":"m","Prefix.AppendTo":"m","Prefix.Bits":"m","Prefix.Contains":"m","Prefix.IsSingleIP":"m","Prefix.IsValid":"m","Prefix.MarshalBinary":"m","Prefix.MarshalText":"m","Prefix.Masked":"m","Prefix.Overlaps":"m","Prefix.String":"m","Prefix.UnmarshalBinary":"m","Prefix.UnmarshalText":"m","PrefixFrom":"f"}},"net/rpc":{"path":"net/rpc","name":"rpc","symbols":{"Accept":"f","Call":"t","Client":"t","Client.Call":"m","Client.Close":"m","Client.Go":"m","ClientCodec":"t","DefaultDebugPath":"c","DefaultRPCPath":"c","DefaultServer":"v","Dial":"f","DialHTTP":"f","DialHTTPPath":"f","ErrShutdown":"v","HandleHTTP":"f","NewClient":"f","NewClientWithCodec":"f","NewServer":"f","Register":"f","RegisterName":"f","Request":"t","Response":"t","ServeCodec":"f","ServeConn":"f","ServeRequest":"f","Server":"t","Server.Accept":"m","Server.HandleHTTP":"m","Server.Register":"m","Server.RegisterName":"m","Server.ServeCodec":"m","Server.ServeConn":"m","Server.ServeHTTP":"m","Server.ServeRequest":"m","ServerCodec":"t","ServerError":"t","ServerError.Error":"m"}},"net/rpc/jsonrpc":{"path":"net/rpc/jsonrpc","name":"jsonrpc","symbols":{"Dial":"f","NewClient":"f","NewClientCodec":"f","NewServerCodec":"f","ServeConn":"f"}},"net/smtp":{"path":"net/smtp","name":"smtp","symbols":{"Auth":"t","CRAMMD5Auth":"f","Client":"t","Client.Auth":"m","Client.Close":"m","Client.Data":"m","Client.Extension":"m","Client.Hello":"m","Client.Mail":"m","Client.Noop":"m","Client.Quit":"m","Client.Rcpt":"m","Client.Reset":"m","Client.StartTLS":"m","Client.TLSConnectionState":"m","Client.Verify":"m","Dial":"f","NewClient":"f","PlainAuth":"f","SendMail":"f","ServerInfo":"t"}},"net/textproto":{"path":"net/textproto","name":"textproto","symbols":{"CanonicalMIMEHeaderKey":"f","Conn":"t","Conn.Close":"m","Conn.Cmd":"m","Dial":"f","Error":"t","Error.Error":"m","MIMEHeader":"t","MIMEHeader.Add":"m","MIMEHeader.Del":"m","MIMEHeader.Get":"m","MIMEHeader.Set":"m","MIMEHeader.Values":"m","NewConn":"f","NewReader":"f","NewWriter":"f","Pipeline":"t","Pipeline.EndRequest":"m","Pipeline.EndResponse":"m","Pipeline.Next":"m","Pipeline.StartRequest":"m","Pipeline.StartResponse":"m","ProtocolError":"t","ProtocolError.Error":"m","Reader":"t","Reader.DotReader":"m","Reader.ReadCodeLine":"m","Reader.ReadContinuedLine":"m","Reader.ReadContinuedLineBytes":"m","Reader.ReadDotBytes":"m","Reader.ReadDotLines":"m","Reader.ReadLine":"m","Reader.ReadLineBytes":"m","Reader.ReadMIMEHeader":"m","Reader.ReadResponse":"m","TrimBytes":"f","TrimString":"f","Writer":"t","Writer.DotWriter":"m","Writer.PrintfLine":"m"}},"net/url":{"path":"net/url","name":"url","symbols":{"Error":"t","Error.Error":"m","Error.Temporary":"m","Error.Timeout":"m","Error.Unwrap":"m","EscapeError":"t","EscapeError.Error":"m","InvalidHostError":"t","InvalidHostError.Error":"m","JoinPath":"f","Parse":"f","ParseQuery":"f","ParseRequestURI":"f","PathEscape":"f","PathUnescape":"f","QueryEscape":"f","QueryUnescape":"f","URL":"t","URL.AppendBinary":"m","URL.EscapedFragment":"m","URL.EscapedPath":"m","URL.Hostname":"m","URL.IsAbs":"m","URL.JoinPath":"m","URL.MarshalBinary":"m","URL.Parse":"m","URL.Port":"m","URL.Query":"m","URL.Redacted":"m","URL.RequestURI":"m","URL.ResolveReference":"m","URL.String":"m","URL.UnmarshalBinary":"m","User":"f","UserPassword":"f","Userinfo":"t","Userinfo.Password":"m","Userinfo.String":"m","Userinfo.Username":"m","Values":"t","Values.Add":"m","Values.Del":"m","Values.Encode":"m","Values.Get":"m","Values.Has":"m","Values.Set":"m"}},"os":{"path":"os","name":"os","symbols":{"Args":"v","Chdir":"f","Chmod":"f","Chown":"f","Chtimes":"f","Clearenv":"f","CopyFS":"f","Create":"f","CreateTemp":"f","DevNull":"c","DirEntry":"t","DirFS":"f","Environ":"f","ErrClosed":"v","ErrDeadlineExceeded":"v","ErrExist":"v","ErrInvalid":"v","ErrNoDeadline":"v","ErrNotExist":"v","ErrPermission":"v","ErrProcessDone":"v","Executable":"f","Exit":"f","Expand":"f","ExpandEnv":"f","File":"t","File.Chdir":"m","File.Chmod":"m","File.Chown":"m","File.Close":"m","File.Fd":"m","File.Name":"m","File.Read":"m","File.ReadAt":"m","File.ReadDir":"m","File.ReadFrom":"m","File.Readdir":"m","File.Readdirnames":"m","File.Seek":"m","File.SetDeadline":"m","File.SetReadDeadline":"m","File.SetWriteDeadline":"m","File.Stat":"m","File.Sync":"m","File.SyscallConn":"m","File.Truncate":"m","File.Write":"m","File.WriteAt":"m","File.WriteString":"m","File.WriteTo":"m","FileInfo":"t","FileMode":"t","FindProcess":"f","Getegid":"f","Getenv":"f","Geteuid":"f","Getgid":"f","Getgroups":"f","Getpagesize":"f","Getpid":"f","Getppid":"f","Getuid":"f","Getwd":"f","Hostname":"f","Interrupt":"v","IsExist":"f","IsNotExist":"f","IsPathSeparator":"f","IsPermission":"f","IsTimeout":"f","Kill":"v","Lchown":"f","Link":"f","LinkError":"t","LinkError.Error":"m","LinkError.Unwrap":"m","LookupEnv":"f","Lstat":"f","Mkdir":"f","MkdirAll":"f","MkdirTemp":"f","ModeAppend":"c","ModeCharDevice":"c","ModeDevice":"c","ModeDir":"c","ModeExclusive":"c","ModeIrregular":"c","ModeNamedPipe":"c","ModePerm":"c","ModeSetgid":"c","ModeSetuid":"c","ModeSocket":"c","ModeSticky":"c","ModeSymlink":"c","ModeTemporary":"c","ModeType":"c","NewFile":"f","NewSyscallError":"f","O_APPEND":"c","O_CREATE":"c","O_EXCL":"c","O_RDONLY":"c","O_RDWR":"c","O_SYNC":"c","O_TRUNC":"c","O_WRONLY":"c","Open":"f","OpenFile":"f","OpenInRoot":"f","OpenRoot":"f","PathError":"t","PathListSeparator":"c","PathSeparator":"c","Pipe":"f","ProcAttr":"t","Process":"t","Process.Kill":"m","Process.Release":"m","Process.Signal":"m","Process.Wait":"m","ProcessState":"t","ProcessState.ExitCode":"m","ProcessState.Exited":"m","ProcessState.Pid":"m","ProcessState.String":"m","ProcessState.Success":"m","ProcessState.Sys":"m","ProcessState.SysUsage":"m","ProcessState.SystemTime":"m","ProcessState.UserTime":"m","ReadDir":"f","ReadFile":"f","Readlink":"f","Remove":"f","RemoveAll":"f","Rename":"f","Root":"t","Root.Chmod":"m","Root.Chown":"m","Root.Chtimes":"m","Root.Close":"m","Root.Create":"m","Root.FS":"m","Root.Lchown":"m","Root.Link":"m","Root.Lstat":"m","Root.Mkdir":"m","Root.MkdirAll":"m","Root.Name":"m","Root.Open":"m","Root.OpenFile":"m","Root.OpenRoot":"m","Root.ReadFile":"m","Root.Readlink":"m","Root.Remove":"m","Root.RemoveAll":"m","Root.Rename":"m","Root.Stat":"m","Root.Symlink":"m","Root.WriteFile":"m","SEEK_CUR":"c","SEEK_END":"c","SEEK_SET":"c","SameFile":"f","Setenv":"f","Signal":"t","StartProcess":"f","Stat":"f","Stderr":"v","Stdin":"v","Stdout":"v","Symlink":"f","SyscallError":"t","SyscallError.Error":"m","SyscallError.Timeout":"m","SyscallError.Unwrap":"m","TempDir":"f","Truncate":"f","Unsetenv":"f","UserCacheDir":"f","UserConfigDir":"f","UserHomeDir":"f","WriteFile":"f"}},"os/exec":{"path":"os/exec","name":"exec","symbols":{"Cmd":"t","Cmd.CombinedOutput":"m","Cmd.Environ":"m","Cmd.Output":"m","Cmd.Run":"m","Cmd.Start":"m","Cmd.StderrPipe":"m","Cmd.StdinPipe":"m","Cmd.StdoutPipe":"m","Cmd.String":"m","Cmd.Wait":"m","Command":"f","CommandContext":"f","ErrDot":"v","ErrNotFound":"v","ErrWaitDelay":"v","Error":"t","Error.Error":"m","Error.Unwrap":"m","ExitError":"t","ExitError.Error":"m","LookPath":"f"}},"os/signal":{"path":"os/signal","name":"signal","symbols":{"Ignore":"f","Ignored":"f","Notify":"f","NotifyContext":"f","Reset":"f","Stop":"f"}},"os/user":{"path":"os/user","name":"user","symbols":{"Current":"f","Group":"t","Lookup":"f","LookupGroup":"f","LookupGroupId":"f","LookupId":"f","UnknownGroupError":"t","UnknownGroupError.Error":"m","UnknownGroupIdError":"t","UnknownGroupIdError.Error":"m","UnknownUserError":"t","UnknownUserError.Error":"m","UnknownUserIdError":"t","UnknownUserIdError.Error":"m","User":"t","User.GroupIds":"m"}},"path":{"path":"path","name":"path","symbols":{"Base":"f","Clean":"f","Dir":"f","ErrBadPattern":"v","Ext":"f","IsAbs":"f","Join":"f","Match":"f","Split":"f"}},"path/filepath":{"path":"path/filepath","name":"filepath","symbols":{"Abs":"f","Base":"f","Clean":"f","Dir":"f","ErrBadPattern":"v","EvalSymlinks":"f","Ext":"f","FromSlash":"f","Glob":"f","HasPrefix":"f","IsAbs":"f","IsLocal":"f","Join":"f","ListSeparator":"c","Localize":"f","Match":"f","Rel":"f","Separator":"c","SkipAll":"v","SkipDir":"v","Split":"f","SplitList":"f","ToSlash":"f","VolumeName":"f","Walk":"f","WalkDir":"f","WalkFunc":"t"}},"plugin":{"path":"plugin","name":"plugin","symbols":{"Open":"f","Plugin":"t","Plugin.Lookup":"m","Symbol":"t"}},"reflect":{"path":"reflect","name":"reflect","symbols":{"Append":"f","AppendSlice":"f","Array":"c","ArrayOf":"f","Bool":"c","BothDir":"c","Chan":"c","ChanDir":"t","ChanDir.String":"m","ChanOf":"f","Complex128":"c","Complex64":"c","Copy":"f","DeepEqual":"f","Float32":"c","Float64":"c","Func":"c","FuncOf":"f","Indirect":"f","Int":"c","Int16":"c","Int32":"c","Int64":"c","Int8":"c","Interface":"c","Invalid":"c","Kind":"t","Kind.String":"m","MakeChan":"f","MakeFunc":"f","MakeMap":"f","MakeMapWithSize":"f","MakeSlice":"f","Map":"c","MapIter":"t","MapIter.Key":"m","MapIter.Next":"m","MapIter.Reset":"m","MapIter.Value":"m","MapOf":"f","Method":"t","Method.IsExported":"m","New":"f","NewAt":"f","Pointer":"c","PointerTo":"f","Ptr":"c","PtrTo":"f","RecvDir":"c","Select":"f","SelectCase":"t","SelectDefault":"c","SelectDir":"t","SelectRecv":"c","SelectSend":"c","SendDir":"c","Slice":"c","SliceAt":"f","SliceHeader":"t","SliceOf":"f","String":"c","StringHeader":"t","Struct":"c","StructField":"t","StructField.IsExported":"m","StructOf":"f","StructTag":"t","StructTag.Get":"m","StructTag.Lookup":"m","Swapper":"f","Type":"t","TypeAssert":"f","TypeFor":"f","TypeOf":"f","Uint":"c","Uint16":"c","Uint32":"c","Uint64":"c","Uint8":"c","Uintptr":"c","UnsafePointer":"c","Value":"t","Value.Addr":"m","Value.Bool":"m","Value.Bytes":"m","Value.Call":"m","Value.CallSlice":"m","Value.CanAddr":"m","Value.CanComplex":"m","Value.CanConvert":"m","Value.CanFloat":"m","Value.CanInt":"m","Value.CanInterface":"m","Value.CanSet":"m","Value.CanUint":"m","Value.Cap":"m","Value.Clear":"m","Value.Close":"m","Value.Comparable":"m","Value.Complex":"m","Value.Convert":"m","Value.Elem":"m","Value.Equal":"m","Value.Field":"m","Value.FieldByIndex":"m","Value.FieldByIndexErr":"m","Value.FieldByName":"m","Value.FieldByNameFunc":"m","Value.Float":"m","Value.Grow":"m","Value.Index":"m","Value.Int":"m","Value.Interface":"m","Value.InterfaceData":"m","Value.IsNil":"m","Value.IsValid":"m","Value.IsZero":"m","Value.Kind":"m","Value.Len":"m","Value.MapIndex":"m","Value.MapKeys":"m","Value.MapRange":"m","Value.Method":"m","Value.MethodByName":"m","Value.NumField":"m","Value.NumMethod":"m","Value.OverflowComplex":"m","Value.OverflowFloat":"m","Value.OverflowInt":"m","Value.OverflowUint":"m","Value.Pointer":"m","Value.Recv":"m","Value.Send":"m","Value.Seq":"m","Value.Seq2":"m","Value.Set":"m","Value.SetBool":"m","Value.SetBytes":"m","Value.SetCap":"m","Value.SetComplex":"m","Value.SetFloat":"m","Value.SetInt":"m","Value.SetIterKey":"m","Value.SetIterValue":"m","Value.SetLen":"m","Value.SetMapIndex":"m","Value.SetPointer":"m","Value.SetString":"m","Value.SetUint":"m","Value.SetZero":"m","Value.Slice":"m","Value.Slice3":"m","Value.String":"m","Value.TryRecv":"m","Value.TrySend":"m","Value.Type":"m","Value.Uint":"m","Value.UnsafeAddr":"m","Value.UnsafePointer":"m","ValueError":"t","ValueError.Error":"m","ValueOf":"f","VisibleFields":"f","Zero":"f"}},"regexp":{"path":"regexp","name":"regexp","symbols":{"Compile":"f","CompilePOSIX":"f","Match":"f","MatchReader":"f","MatchString":"f","MustCompile":"f","MustCompilePOSIX":"f","QuoteMeta":"f","Regexp":"t","Regexp.AppendText":"m","Regexp.Copy":"m","Regexp.Expand":"m","Regexp.ExpandString":"m","Regexp.Find":"m","Regexp.FindAll":"m","Regexp.FindAllIndex":"m","Regexp.FindAllString":"m","Regexp.FindAllStringIndex":"m","Regexp.FindAllStringSubmatch":"m","Regexp.FindAllStringSubmatchIndex":"m","Regexp.FindAllSubmatch":"m","Regexp.FindAllSubmatchIndex":"m","Regexp.FindIndex":"m","Regexp.FindReaderIndex":"m","Regexp.FindReaderSubmatchIndex":"m","Regexp.FindString":"m","Regexp.FindStringIndex":"m","Regexp.FindStringSubmatch":"m","Regexp.FindStringSubmatchIndex":"m","Regexp.FindSubmatch":"m","Regexp.FindSubmatchIndex":"m","Regexp.LiteralPrefix":"m","Regexp.Longest":"m","Regexp.MarshalText":"m","Regexp.Match":"m","Regexp.MatchReader":"m","Regexp.MatchString":"m","Regexp.NumSubexp":"m","Regexp.ReplaceAll":"m","Regexp.ReplaceAllFunc":"m","Regexp.ReplaceAllLiteral":"m","Regexp.ReplaceAllLiteralString":"m","Regexp.ReplaceAllString":"m","Regexp.ReplaceAllStringFunc":"m","Regexp.Split":"m","Regexp.String":"m","Regexp.SubexpIndex":"m","Regexp.SubexpNames":"m","Regexp.UnmarshalText":"m"}},"regexp/syntax":{"path":"regexp/syntax","name":"syntax","symbols":{"ClassNL":"c","Compile":"f","DotNL":"c","EmptyBeginLine":"c","EmptyBeginText":"c","EmptyEndLine":"c","EmptyEndText":"c","EmptyNoWordBoundary":"c","EmptyOp":"t","EmptyOpContext":"f","EmptyWordBoundary":"c","ErrInternalError":"c","ErrInvalidCharClass":"c","ErrInvalidCharRange":"c","ErrInvalidEscape":"c","ErrInvalidNamedCapture":"c","ErrInvalidPerlOp":"c","ErrInvalidRepeatOp":"c","ErrInvalidRepeatSize":"c","ErrInvalidUTF8":"c","ErrLarge":"c","ErrMissingBracket":"c","ErrMissingParen":"c","ErrMissingRepeatArgument":"c","ErrNestingDepth":"c","ErrTrailingBackslash":"c","ErrUnexpectedParen":"c","Error":"t","Error.Error":"m","ErrorCode":"t","ErrorCode.String":"m","Flags":"t","FoldCase":"c","Inst":"t","Inst.MatchEmptyWidth":"m","Inst.MatchRune":"m","Inst.MatchRunePos":"m","Inst.String":"m","InstAlt":"c","InstAltMatch":"c","InstCapture":"c","InstEmptyWidth":"c","InstFail":"c","InstMatch":"c","InstNop":"c","InstOp":"t","InstOp.String":"m","InstRune":"c","InstRune1":"c","InstRuneAny":"c","InstRuneAnyNotNL":"c","IsWordChar":"f","Literal":"c","MatchNL":"c","NonGreedy":"c","OneLine":"c","Op":"t","Op.String":"m","OpAlternate":"c","OpAnyChar":"c","OpAnyCharNotNL":"c","OpBeginLine":"c","OpBeginText":"c","OpCapture":"c","OpCharClass":"c","OpConcat":"c","OpEmptyMatch":"c","OpEndLine":"c","OpEndText":"c","OpLiteral":"c","OpNoMatch":"c","OpNoWordBoundary":"c","OpPlus":"c","OpQuest":"c","OpRepeat":"c","OpStar":"c","OpWordBoundary":"c","POSIX":"c","Parse":"f","Perl":"c","PerlX":"c","Prog":"t","Prog.Prefix":"m","Prog.StartCond":"m","Prog.String":"m","Regexp":"t","Regexp.CapNames":"m","Regexp.Equal":"m","Regexp.MaxCap":"m","Regexp.Simplify":"m","Regexp.String":"m","Simple":"c","UnicodeGroups":"c","WasDollar":"c"}},"runtime":{"path":"runtime","name":"runtime","symbols":{"AddCleanup":"f","BlockProfile":"f","BlockProfileRecord":"t","Breakpoint":"f","CPUProfile":"f","Caller":"f","Callers":"f","CallersFrames":"f","Cleanup":"t","Cleanup.Stop":"m","Compiler":"c","Error":"t","Frame":"t","Frames":"t","Frames.Next":"m","Func":"t","Func.Entry":"m","Func.FileLine":"m","Func.Name":"m","FuncForPC":"f","GC":"f","GOARCH":"c","GOMAXPROCS":"f","GOOS":"c","GOROOT":"f","Goexit":"f","GoroutineProfile":"f","Gosched":"f","KeepAlive":"f","LockOSThread":"f","MemProfile":"f","MemProfileRate":"v","MemProfileRecord":"t","MemProfileRecord.InUseBytes":"m","MemProfileRecord.InUseObjects":"m","MemProfileRecord.Stack":"m","MemStats":"t","MutexProfile":"f","NumCPU":"f","NumCgoCall":"f","NumGoroutine":"f","PanicNilError":"t","PanicNilError.Error":"m","PanicNilError.RuntimeError":"m","Pinner":"t","Pinner.Pin":"m","Pinner.Unpin":"m","ReadMemStats":"f","ReadTrace":"f","SetBlockProfileRate":"f","SetCPUProfileRate":"f","SetCgoTraceback":"f","SetDefaultGOMAXPROCS":"f","SetFinalizer":"f","SetMutexProfileFraction":"f","Stack":"f","StackRecord":"t","StackRecord.Stack":"m","StartTrace":"f","StopTrace":"f","ThreadCreateProfile":"f","TypeAssertionError":"t","TypeAssertionError.Error":"m","TypeAssertionError.RuntimeError":"m","UnlockOSThread":"f","Version":"f"}},"runtime/cgo":{"path":"runtime/cgo","name":"cgo","symbols":{"Handle":"t","Handle.Delete":"m","Handle.Value":"m","Incomplete":"t","NewHandle":"f"}},"runtime/coverage":{"path":"runtime/coverage","name":"coverage","symbols":{"ClearCounters":"f","WriteCounters":"f","WriteCountersDir":"f","WriteMeta":"f","WriteMetaDir":"f"}},"runtime/debug":{"path":"runtime/debug","name":"debug","symbols":{"BuildInfo":"t","BuildInfo.String":"m","BuildSetting":"t","CrashOptions":"t","FreeOSMemory":"f","GCStats":"t","Module":"t","ParseBuildInfo":"f","PrintStack":"f","ReadBuildInfo":"f","ReadGCStats":"f","SetCrashOutput":"f","SetGCPercent":"f","SetMaxStack":"f","SetMaxThreads":"f","SetMemoryLimit":"f","SetPanicOnFault":"f","SetTraceback":"f","Stack":"f","WriteHeapDump":"f"}},"runtime/metrics":{"path":"runtime/metrics","name":"metrics","symbols":{"All":"f","Description":"t","Float64Histogram":"t","KindBad":"c","KindFloat64":"c","KindFloat64Histogram":"c","KindUint64":"c","Read":"f","Sample":"t","Value":"t","Value.Float64":"m","Value.Float64Histogram":"m","Value.Kind":"m","Value.Uint64":"m","ValueKind":"t"}},"runtime/pprof":{"path":"runtime/pprof","name":"pprof","symbols":{"Do":"f","ForLabels":"f","Label":"f","LabelSet":"t","Labels":"f","Lookup":"f","NewProfile":"f","Profile":"t","Profile.Add":"m","Profile.Count":"m","Profile.Name":"m","Profile.Remove":"m","Profile.WriteTo":"m","Profiles":"f","SetGoroutineLabels":"f","StartCPUProfile":"f","StopCPUProfile":"f","WithLabels":"f","WriteHeapProfile":"f"}},"runtime/trace":{"path":"runtime/trace","name":"trace","symbols":{"FlightRecorder":"t","FlightRecorder.Enabled":"m","FlightRecorder.Start":"m","FlightRecorder.Stop":"m","FlightRecorder.WriteTo":"m","FlightRecorderConfig":"t","IsEnabled":"f","Log":"f","Logf":"f","NewFlightRecorder":"f","NewTask":"f","Region":"t","Region.End":"m","Start":"f","StartRegion":"f","Stop":"f","Task":"t","Task.End":"m","WithRegion":"f"}},"slices":{"path":"slices","name":"slices","symbols":{"All":"f","AppendSeq":"f","Backward":"f","BinarySearch":"f","BinarySearchFunc":"f","Chunk":"f","Clip":"f","Clone":"f","Collect":"f","Compact":"f","CompactFunc":"f","Compare":"f","CompareFunc":"f","Concat":"f","Contains":"f","ContainsFunc":"f","Delete":"f","DeleteFunc":"f","Equal":"f","EqualFunc":"f","Grow":"f","Index":"f","IndexFunc":"f","Insert":"f","IsSorted":"f","IsSortedFunc":"f","Max":"f","MaxFunc":"f","Min":"f","MinFunc":"f","Repeat":"f","Replace":"f","Reverse":"f","Sort":"f","SortFunc":"f","SortStableFunc":"f","Sorted":"f","SortedFunc":"f","SortedStableFunc":"f","Values":"f"}},"sort":{"path":"sort","name":"sort","symbols":{"Find":"f","Float64Slice":"t","Float64Slice.Len":"m","Float64Slice.Less":"m","Float64Slice.Search":"m","Float64Slice.Sort":"m","Float64Slice.Swap":"m","Float64s":"f","Float64sAreSorted":"f","IntSlice":"t","IntSlice.Len":"m","IntSlice.Less":"m","IntSlice.Search":"m","IntSlice.Sort":"m","IntSlice.Swap":"m","Interface":"t","Ints":"f","IntsAreSorted":"f","IsSorted":"f","Reverse":"f","Search":"f","SearchFloat64s":"f","SearchInts":"f","SearchStrings":"f","Slice":"f","SliceIsSorted":"f","SliceStable":"f","Sort":"f","Stable":"f","StringSlice":"t","StringSlice.Len":"m","StringSlice.Less":"m","StringSlice.Search":"m","StringSlice.Sort":"m","StringSlice.Swap":"m","Strings":"f","StringsAreSorted":"f"}},"strconv":{"path":"strconv","name":"strconv","symbols":{"AppendBool":"f","AppendFloat":"f","AppendInt":"f","AppendQuote":"f","AppendQuoteRune":"f","AppendQuoteRuneToASCII":"f","AppendQuoteRuneToGraphic":"f","AppendQuoteToASCII":"f","AppendQuoteToGraphic":"f","AppendUint":"f","Atoi":"f","CanBackquote":"f","ErrRange":"v","ErrSyntax":"v","FormatBool":"f","FormatComplex":"f","FormatFloat":"f","FormatInt":"f","FormatUint":"f","IntSize":"c","IsGraphic":"f","IsPrint":"f","Itoa":"f","NumError":"t","NumError.Error":"m","NumError.Unwrap":"m","ParseBool":"f","ParseComplex":"f","ParseFloat":"f","ParseInt":"f","ParseUint":"f","Quote":"f","QuoteRune":"f","QuoteRuneToASCII":"f","QuoteRuneToGraphic":"f","QuoteToASCII":"f","QuoteToGraphic":"f","QuotedPrefix":"f","Unquote":"f","UnquoteChar":"f"}},"strings":{"path":"strings","name":"strings","symbols":{"Builder":"t","Builder.Cap":"m","Builder.Grow":"m","Builder.Len":"m","Builder.Reset":"m","Builder.String":"m","Builder.Write":"m","Builder.WriteByte":"m","Builder.WriteRune":"m","Builder.WriteString":"m","Clone":"f","Compare":"f","Contains":"f","ContainsAny":"f","ContainsFunc":"f","ContainsRune":"f","Count":"f","Cut":"f","CutPrefix":"f","CutSuffix":"f","EqualFold":"f","Fields":"f","FieldsFunc":"f","FieldsFuncSeq":"f","FieldsSeq":"f","HasPrefix":"f","HasSuffix":"f","Index":"f","IndexAny":"f","IndexByte":"f","IndexFunc":"f","IndexRune":"f","Join":"f","LastIndex":"f","LastIndexAny":"f","LastIndexByte":"f","LastIndexFunc":"f","Lines":"f","Map":"f","NewReader":"f","NewReplacer":"f","Reader":"t","Reader.Len":"m","Reader.Read":"m","Reader.ReadAt":"m","Reader.ReadByte":"m","Reader.ReadRune":"m","Reader.Reset":"m","Reader.Seek":"m","Reader.Size":"m","Reader.UnreadByte":"m","Reader.UnreadRune":"m","Reader.WriteTo":"m","Repeat":"f","Replace":"f","ReplaceAll":"f","Replacer":"t","Replacer.Replace":"m","Replacer.WriteString":"m","Split":"f","SplitAfter":"f","SplitAfterN":"f","SplitAfterSeq":"f","SplitN":"f","SplitSeq":"f","Title":"f","ToLower":"f","ToLowerSpecial":"f","ToTitle":"f","ToTitleSpecial":"f","ToUpper":"f","ToUpperSpecial":"f","ToValidUTF8":"f","Trim":"f","TrimFunc":"f","TrimLeft":"f","TrimLeftFunc":"f","TrimPrefix":"f","TrimRight":"f","TrimRightFunc":"f","TrimSpace":"f","TrimSuffix":"f"}},"structs":{"path":"structs","name":"structs","symbols":{"HostLayout":"t"}},"sync":{"path":"sync","name":"sync","symbols":{"Cond":"t","Cond.Broadcast":"m","Cond.Signal":"m","Cond.Wait":"m","Locker":"t","Map":"t","Map.Clear":"m","Map.CompareAndDelete":"m","Map.CompareAndSwap":"m","Map.Delete":"m","Map.Load":"m","Map.LoadAndDelete":"m","Map.LoadOrStore":"m","Map.Range":"m","Map.Store":"m","Map.Swap":"m","Mutex":"t","Mutex.Lock":"m","Mutex.TryLock":"m","Mutex.Unlock":"m","NewCond":"f","Once":"t","Once.Do":"m","OnceFunc":"f","OnceValue":"f","OnceValues":"f","Pool":"t","Pool.Get":"m","Pool.Put":"m","RWMutex":"t","RWMutex.Lock":"m","RWMutex.RLock":"m","RWMutex.RLocker":"m","RWMutex.RUnlock":"m","RWMutex.TryLock":"m","RWMutex.TryRLock":"m","RWMutex.Unlock":"m","WaitGroup":"t","WaitGroup.Add":"m","WaitGroup.Done":"m","WaitGroup.Go":"m","WaitGroup.Wait":"m"}},"sync/atomic":{"path":"sync/atomic","name":"atomic","symbols":{"AddInt32":"f","AddInt64":"f","AddUint32":"f","AddUint64":"f","AddUintptr":"f","AndInt32":"f","AndInt64":"f","AndUint32":"f","AndUint64":"f","AndUintptr":"f","Bool":"t","Bool.CompareAndSwap":"m","Bool.Load":"m","Bool.Store":"m","Bool.Swap":"m","CompareAndSwapInt32":"f","CompareAndSwapInt64":"f","CompareAndSwapPointer":"f","CompareAndSwapUint32":"f","CompareAndSwapUint64":"f","CompareAndSwapUintptr":"f","Int32":"t","Int32.Add":"m","Int32.And":"m","Int32.CompareAndSwap":"m","Int32.Load":"m","Int32.Or":"m","Int32.Store":"m","Int32.Swap":"m","Int64":"t","Int64.Add":"m","Int64.And":"m","Int64.CompareAndSwap":"m","Int64.Load":"m","Int64.Or":"m","Int64.Store":"m","Int64.Swap":"m","LoadInt32":"f","LoadInt64":"f","LoadPointer":"f","LoadUint32":"f","LoadUint64":"f","LoadUintptr":"f","OrInt32":"f","OrInt64":"f","OrUint32":"f","OrUint64":"f","OrUintptr":"f","Pointer":"t","StoreInt32":"f","StoreInt64":"f","StorePointer":"f","StoreUint32":"f","StoreUint64":"f","StoreUintptr":"f","SwapInt32":"f","SwapInt64":"f","SwapPointer":"f","SwapUint32":"f","SwapUint64":"f","SwapUintptr":"f","Uint32":"t","Uint32.Add":"m","Uint32.And":"m","Uint32.CompareAndSwap":"m","Uint32.Load":"m","Uint32.Or":"m","Uint32.Store":"m","Uint32.Swap":"m","Uint64":"t","Uint64.Add":"m","Uint64.And":"m","Uint64.CompareAndSwap":"m","Uint64.Load":"m","Uint64.Or":"m","Uint64.Store":"m","Uint64.Swap":"m","Uintptr":"t","Uintptr.Add":"m","Uintptr.And":"m","Uintptr.CompareAndSwap":"m","Uintptr.Load":"m","Uintptr.Or":"m","Uintptr.Store":"m","Uintptr.Swap":"m","Value":"t","Value.CompareAndSwap":"m","Value.Load":"m","Value.Store":"m","Value.Swap":"m"}},"syscall":{"path":"syscall","name":"syscall","symbols":{"AF_ALG":"c","AF_APPLETALK":"c","AF_ASH":"c","AF_ATMPVC":"c","AF_ATMSVC":"c","AF_AX25":"c","AF_BLUETOOTH":"c","AF_BRIDGE":"c","AF_CAIF":"c","AF_CAN":"c","AF_DECnet":"c","AF_ECONET":"c","AF_FILE":"c","AF_IEEE802154":"c","AF_INET":"c","AF_INET6":"c","AF_IPX":"c","AF_IRDA":"c","AF_ISDN":"c","AF_IUCV":"c","AF_KEY":"c","AF_LLC":"c","AF_LOCAL":"c","AF_MAX":"c","AF_NETBEUI":"c","AF_NETLINK":"c","AF_NETROM":"c","AF_PACKET":"c","AF_PHONET":"c","AF_PPPOX":"c","AF_RDS":"c","AF_ROSE":"c","AF_ROUTE":"c","AF_RXRPC":"c","AF_SECURITY":"c","AF_SNA":"c","AF_TIPC":"c","AF_UNIX":"c","AF_UNSPEC":"c","AF_WANPIPE":"c","AF_X25":"c","ARPHRD_ADAPT":"c","ARPHRD_APPLETLK":"c","ARPHRD_ARCNET":"c","ARPHRD_ASH":"c","ARPHRD_ATM":"c","ARPHRD_AX25":"c","ARPHRD_BIF":"c","ARPHRD_CHAOS":"c","ARPHRD_CISCO":"c","ARPHRD_CSLIP":"c","ARPHRD_CSLIP6":"c","ARPHRD_DDCMP":"c","ARPHRD_DLCI":"c","ARPHRD_ECONET":"c","ARPHRD_EETHER":"c","ARPHRD_ETHER":"c","ARPHRD_EUI64":"c","ARPHRD_FCAL":"c","ARPHRD_FCFABRIC":"c","ARPHRD_FCPL":"c","ARPHRD_FCPP":"c","ARPHRD_FDDI":"c","ARPHRD_FRAD":"c","ARPHRD_HDLC":"c","ARPHRD_HIPPI":"c","ARPHRD_HWX25":"c","ARPHRD_IEEE1394":"c","ARPHRD_IEEE802":"c","ARPHRD_IEEE80211":"c","ARPHRD_IEEE80211_PRISM":"c","ARPHRD_IEEE80211_RADIOTAP":"c","ARPHRD_IEEE802154":"c","ARPHRD_IEEE802154_PHY":"c","ARPHRD_IEEE802_TR":"c","ARPHRD_INFINIBAND":"c","ARPHRD_IPDDP":"c","ARPHRD_IPGRE":"c","ARPHRD_IRDA":"c","ARPHRD_LAPB":"c","ARPHRD_LOCALTLK":"c","ARPHRD_LOOPBACK":"c","ARPHRD_METRICOM":"c","ARPHRD_NETROM":"c","ARPHRD_NONE":"c","ARPHRD_PIMREG":"c","ARPHRD_PPP":"c","ARPHRD_PRONET":"c","ARPHRD_RAWHDLC":"c","ARPHRD_ROSE":"c","ARPHRD_RSRVD":"c","ARPHRD_SIT":"c","ARPHRD_SKIP":"c","ARPHRD_SLIP":"c","ARPHRD_SLIP6":"c","ARPHRD_TUNNEL":"c","ARPHRD_TUNNEL6":"c","ARPHRD_VOID":"c","ARPHRD_X25":"c","Accept":"f","Accept4":"f","Access":"f","Acct":"f","Adjtimex":"f","AllThreadsSyscall":"f","AllThreadsSyscall6":"f","AttachLsf":"f","B0":"c","B1000000":"c","B110":"c","B115200":"c","B1152000":"c","B1200":"c","B134":"c","B150":"c","B1500000":"c","B1800":"c","B19200":"c","B200":"c","B2000000":"c","B230400":"c","B2400":"c","B2500000":"c","B300":"c","B3000000":"c","B3500000":"c","B38400":"c","B4000000":"c","B460800":"c","B4800":"c","B50":"c","B500000":"c","B57600":"c","B576000":"c","B600":"c","B75":"c","B921600":"c","B9600":"c","BPF_A":"c","BPF_ABS":"c","BPF_ADD":"c","BPF_ALU":"c","BPF_AND":"c","BPF_B":"c","BPF_DIV":"c","BPF_H":"c","BPF_IMM":"c","BPF_IND":"c","BPF_JA":"c","BPF_JEQ":"c","BPF_JGE":"c","BPF_JGT":"c","BPF_JMP":"c","BPF_JSET":"c","BPF_K":"c","BPF_LD":"c","BPF_LDX":"c","BPF_LEN":"c","BPF_LSH":"c","BPF_MAJOR_VERSION":"c","BPF_MAXINSNS":"c","BPF_MEM":"c","BPF_MEMWORDS":"c","BPF_MINOR_VERSION":"c","BPF_MISC":"c","BPF_MSH":"c","BPF_MUL":"c","BPF_NEG":"c","BPF_OR":"c","BPF_RET":"c","BPF_RSH":"c","BPF_ST":"c","BPF_STX":"c","BPF_SUB":"c","BPF_TAX":"c","BPF_TXA":"c","BPF_W":"c","BPF_X":"c","BRKINT":"c","Bind":"f","BindToDevice":"f","BytePtrFromString":"f","ByteSliceFromString":"f","CLOCAL":"c","CLONE_CHILD_CLEARTID":"c","CLONE_CHILD_SETTID":"c","CLONE_CLEAR_SIGHAND":"c","CLONE_DETACHED":"c","CLONE_FILES":"c","CLONE_FS":"c","CLONE_INTO_CGROUP":"c","CLONE_IO":"c","CLONE_NEWCGROUP":"c","CLONE_NEWIPC":"c","CLONE_NEWNET":"c","CLONE_NEWNS":"c","CLONE_NEWPID":"c","CLONE_NEWTIME":"c","CLONE_NEWUSER":"c","CLONE_NEWUTS":"c","CLONE_PARENT":"c","CLONE_PARENT_SETTID":"c","CLONE_PIDFD":"c","CLONE_PTRACE":"c","CLONE_SETTLS":"c","CLONE_SIGHAND":"c","CLONE_SYSVSEM":"c","CLONE_THREAD":"c","CLONE_UNTRACED":"c","CLONE_VFORK":"c","CLONE_VM":"c","CREAD":"c","CS5":"c","CS6":"c","CS7":"c","CS8":"c","CSIZE":"c","CSTOPB":"c","Chdir":"f","Chmod":"f","Chown":"f","Chroot":"f","Clearenv":"f","Close":"f","CloseOnExec":"f","CmsgLen":"f","CmsgSpace":"f","Cmsghdr":"t","Cmsghdr.SetLen":"m","Conn":"t","Connect":"f","Creat":"f","Credential":"t","DT_BLK":"c","DT_CHR":"c","DT_DIR":"c","DT_FIFO":"c","DT_LNK":"c","DT_REG":"c","DT_SOCK":"c","DT_UNKNOWN":"c","DT_WHT":"c","DetachLsf":"f","Dirent":"t","Dup":"f","Dup2":"f","Dup3":"f","E2BIG":"c","EACCES":"c","EADDRINUSE":"c","EADDRNOTAVAIL":"c","EADV":"c","EAFNOSUPPORT":"c","EAGAIN":"c","EALREADY":"c","EBADE":"c","EBADF":"c","EBADFD":"c","EBADMSG":"c","EBADR":"c","EBADRQC":"c","EBADSLT":"c","EBFONT":"c","EBUSY":"c","ECANCELED":"c","ECHILD":"c","ECHO":"c","ECHOCTL":"c","ECHOE":"c","ECHOK":"c","ECHOKE":"c","ECHONL":"c","ECHOPRT":"c","ECHRNG":"c","ECOMM":"c","ECONNABORTED":"c","ECONNREFUSED":"c","ECONNRESET":"c","EDEADLK":"c","EDEADLOCK":"c","EDESTADDRREQ":"c","EDOM":"c","EDOTDOT":"c","EDQUOT":"c","EEXIST":"c","EFAULT":"c","EFBIG":"c","EHOSTDOWN":"c","EHOSTUNREACH":"c","EIDRM":"c","EILSEQ":"c","EINPROGRESS":"c","EINTR":"c","EINVAL":"c","EIO":"c","EISCONN":"c","EISDIR":"c","EISNAM":"c","EKEYEXPIRED":"c","EKEYREJECTED":"c","EKEYREVOKED":"c","EL2HLT":"c","EL2NSYNC":"c","EL3HLT":"c","EL3RST":"c","ELIBACC":"c","ELIBBAD":"c","ELIBEXEC":"c","ELIBMAX":"c","ELIBSCN":"c","ELNRNG":"c","ELOOP":"c","EMEDIUMTYPE":"c","EMFILE":"c","EMLINK":"c","EMSGSIZE":"c","EMULTIHOP":"c","ENAMETOOLONG":"c","ENAVAIL":"c","ENETDOWN":"c","ENETRESET":"c","ENETUNREACH":"c","ENFILE":"c","ENOANO":"c","ENOBUFS":"c","ENOCSI":"c","ENODATA":"c","ENODEV":"c","ENOENT":"c","ENOEXEC":"c","ENOKEY":"c","ENOLCK":"c","ENOLINK":"c","ENOMEDIUM":"c","ENOMEM":"c","ENOMSG":"c","ENONET":"c","ENOPKG":"c","ENOPROTOOPT":"c","ENOSPC":"c","ENOSR":"c","ENOSTR":"c","ENOSYS":"c","ENOTBLK":"c","ENOTCONN":"c","ENOTDIR":"c","ENOTEMPTY":"c","ENOTNAM":"c","ENOTRECOVERABLE":"c","ENOTSOCK":"c","ENOTSUP":"c","ENOTTY":"c","ENOTUNIQ":"c","ENXIO":"c","EOPNOTSUPP":"c","EOVERFLOW":"c","EOWNERDEAD":"c","EPERM":"c","EPFNOSUPPORT":"c","EPIPE":"c","EPOLLERR":"c","EPOLLET":"c","EPOLLHUP":"c","EPOLLIN":"c","EPOLLMSG":"c","EPOLLONESHOT":"c","EPOLLOUT":"c","EPOLLPRI":"c","EPOLLRDBAND":"c","EPOLLRDHUP":"c","EPOLLRDNORM":"c","EPOLLWRBAND":"c","EPOLLWRNORM":"c","EPOLL_CLOEXEC":"c","EPOLL_CTL_ADD":"c","EPOLL_CTL_DEL":"c","EPOLL_CTL_MOD":"c","EPOLL_NONBLOCK":"c","EPROTO":"c","EPROTONOSUPPORT":"c","EPROTOTYPE":"c","ERANGE":"c","EREMCHG":"c","EREMOTE":"c","EREMOTEIO":"c","ERESTART":"c","ERFKILL":"c","EROFS":"c","ESHUTDOWN":"c","ESOCKTNOSUPPORT":"c","ESPIPE":"c","ESRCH":"c","ESRMNT":"c","ESTALE":"c","ESTRPIPE":"c","ETH_P_1588":"c","ETH_P_8021Q":"c","ETH_P_802_2":"c","ETH_P_802_3":"c","ETH_P_AARP":"c","ETH_P_ALL":"c","ETH_P_AOE":"c","ETH_P_ARCNET":"c","ETH_P_ARP":"c","ETH_P_ATALK":"c","ETH_P_ATMFATE":"c","ETH_P_ATMMPOA":"c","ETH_P_AX25":"c","ETH_P_BPQ":"c","ETH_P_CAIF":"c","ETH_P_CAN":"c","ETH_P_CONTROL":"c","ETH_P_CUST":"c","ETH_P_DDCMP":"c","ETH_P_DEC":"c","ETH_P_DIAG":"c","ETH_P_DNA_DL":"c","ETH_P_DNA_RC":"c","ETH_P_DNA_RT":"c","ETH_P_DSA":"c","ETH_P_ECONET":"c","ETH_P_EDSA":"c","ETH_P_FCOE":"c","ETH_P_FIP":"c","ETH_P_HDLC":"c","ETH_P_IEEE802154":"c","ETH_P_IEEEPUP":"c","ETH_P_IEEEPUPAT":"c","ETH_P_IP":"c","ETH_P_IPV6":"c","ETH_P_IPX":"c","ETH_P_IRDA":"c","ETH_P_LAT":"c","ETH_P_LINK_CTL":"c","ETH_P_LOCALTALK":"c","ETH_P_LOOP":"c","ETH_P_MOBITEX":"c","ETH_P_MPLS_MC":"c","ETH_P_MPLS_UC":"c","ETH_P_PAE":"c","ETH_P_PAUSE":"c","ETH_P_PHONET":"c","ETH_P_PPPTALK":"c","ETH_P_PPP_DISC":"c","ETH_P_PPP_MP":"c","ETH_P_PPP_SES":"c","ETH_P_PUP":"c","ETH_P_PUPAT":"c","ETH_P_RARP":"c","ETH_P_SCA":"c","ETH_P_SLOW":"c","ETH_P_SNAP":"c","ETH_P_TEB":"c","ETH_P_TIPC":"c","ETH_P_TRAILER":"c","ETH_P_TR_802_2":"c","ETH_P_WAN_PPP":"c","ETH_P_WCCP":"c","ETH_P_X25":"c","ETIME":"c","ETIMEDOUT":"c","ETOOMANYREFS":"c","ETXTBSY":"c","EUCLEAN":"c","EUNATCH":"c","EUSERS":"c","EWOULDBLOCK":"c","EXDEV":"c","EXFULL":"c","Environ":"f","EpollCreate":"f","EpollCreate1":"f","EpollCtl":"f","EpollEvent":"t","EpollWait":"f","Errno":"t","Errno.Error":"m","Errno.Is":"m","Errno.Temporary":"m","Errno.Timeout":"m","Exec":"f","Exit":"f","FD_CLOEXEC":"c","FD_SETSIZE":"c","FLUSHO":"c","F_DUPFD":"c","F_DUPFD_CLOEXEC":"c","F_EXLCK":"c","F_GETFD":"c","F_GETFL":"c","F_GETLEASE":"c","F_GETLK":"c","F_GETLK64":"c","F_GETOWN":"c","F_GETOWN_EX":"c","F_GETPIPE_SZ":"c","F_GETSIG":"c","F_LOCK":"c","F_NOTIFY":"c","F_OK":"c","F_RDLCK":"c","F_SETFD":"c","F_SETFL":"c","F_SETLEASE":"c","F_SETLK":"c","F_SETLK64":"c","F_SETLKW":"c","F_SETLKW64":"c","F_SETOWN":"c","F_SETOWN_EX":"c","F_SETPIPE_SZ":"c","F_SETSIG":"c","F_SHLCK":"c","F_TEST":"c","F_TLOCK":"c","F_ULOCK":"c","F_UNLCK":"c","F_WRLCK":"c","Faccessat":"f","Fallocate":"f","Fchdir":"f","Fchmod":"f","Fchmodat":"f","Fchown":"f","Fchownat":"f","FcntlFlock":"f","FdSet":"t","Fdatasync":"f","Flock":"f","Flock_t":"t","ForkExec":"f","ForkLock":"v","Fsid":"t","Fstat":"f","Fstatfs":"f","Fsync":"f","Ftruncate":"f","Futimes":"f","Futimesat":"f","Getcwd":"f","Getdents":"f","Getegid":"f","Getenv":"f","Geteuid":"f","Getgid":"f","Getgroups":"f","Getpagesize":"f","Getpeername":"f","Getpgid":"f","Getpgrp":"f","Getpid":"f","Getppid":"f","Getpriority":"f","Getrlimit":"f","Getrusage":"f","Getsockname":"f","GetsockoptICMPv6Filter":"f","GetsockoptIPMreq":"f","GetsockoptIPMreqn":"f","GetsockoptIPv6MTUInfo":"f","GetsockoptIPv6Mreq":"f","GetsockoptInet4Addr":"f","GetsockoptInt":"f","GetsockoptUcred":"f","Gettid":"f","Gettimeofday":"f","Getuid":"f","Getwd":"f","Getxattr":"f","HUPCL":"c","ICANON":"c","ICMPV6_FILTER":"c","ICMPv6Filter":"t","ICRNL":"c","IEXTEN":"c","IFA_ADDRESS":"c","IFA_ANYCAST":"c","IFA_BROADCAST":"c","IFA_CACHEINFO":"c","IFA_F_DADFAILED":"c","IFA_F_DEPRECATED":"c","IFA_F_HOMEADDRESS":"c","IFA_F_NODAD":"c","IFA_F_OPTIMISTIC":"c","IFA_F_PERMANENT":"c","IFA_F_SECONDARY":"c","IFA_F_TEMPORARY":"c","IFA_F_TENTATIVE":"c","IFA_LABEL":"c","IFA_LOCAL":"c","IFA_MAX":"c","IFA_MULTICAST":"c","IFA_UNSPEC":"c","IFF_ALLMULTI":"c","IFF_AUTOMEDIA":"c","IFF_BROADCAST":"c","IFF_DEBUG":"c","IFF_DYNAMIC":"c","IFF_LOOPBACK":"c","IFF_MASTER":"c","IFF_MULTICAST":"c","IFF_NOARP":"c","IFF_NOTRAILERS":"c","IFF_NO_PI":"c","IFF_ONE_QUEUE":"c","IFF_POINTOPOINT":"c","IFF_PORTSEL":"c","IFF_PROMISC":"c","IFF_RUNNING":"c","IFF_SLAVE":"c","IFF_TAP":"c","IFF_TUN":"c","IFF_TUN_EXCL":"c","IFF_UP":"c","IFF_VNET_HDR":"c","IFLA_ADDRESS":"c","IFLA_BROADCAST":"c","IFLA_COST":"c","IFLA_IFALIAS":"c","IFLA_IFNAME":"c","IFLA_LINK":"c","IFLA_LINKINFO":"c","IFLA_LINKMODE":"c","IFLA_MAP":"c","IFLA_MASTER":"c","IFLA_MAX":"c","IFLA_MTU":"c","IFLA_NET_NS_PID":"c","IFLA_OPERSTATE":"c","IFLA_PRIORITY":"c","IFLA_PROTINFO":"c","IFLA_QDISC":"c","IFLA_STATS":"c","IFLA_TXQLEN":"c","IFLA_UNSPEC":"c","IFLA_WEIGHT":"c","IFLA_WIRELESS":"c","IFNAMSIZ":"c","IGNBRK":"c","IGNCR":"c","IGNPAR":"c","IMAXBEL":"c","INLCR":"c","INPCK":"c","IN_ACCESS":"c","IN_ALL_EVENTS":"c","IN_ATTRIB":"c","IN_CLASSA_HOST":"c","IN_CLASSA_MAX":"c","IN_CLASSA_NET":"c","IN_CLASSA_NSHIFT":"c","IN_CLASSB_HOST":"c","IN_CLASSB_MAX":"c","IN_CLASSB_NET":"c","IN_CLASSB_NSHIFT":"c","IN_CLASSC_HOST":"c","IN_CLASSC_NET":"c","IN_CLASSC_NSHIFT":"c","IN_CLOEXEC":"c","IN_CLOSE":"c","IN_CLOSE_NOWRITE":"c","IN_CLOSE_WRITE":"c","IN_CREATE":"c","IN_DELETE":"c","IN_DELETE_SELF":"c","IN_DONT_FOLLOW":"c","IN_EXCL_UNLINK":"c","IN_IGNORED":"c","IN_ISDIR":"c","IN_LOOPBACKNET":"c","IN_MASK_ADD":"c","IN_MODIFY":"c","IN_MOVE":"c","IN_MOVED_FROM":"c","IN_MOVED_TO":"c","IN_MOVE_SELF":"c","IN_NONBLOCK":"c","IN_ONESHOT":"c","IN_ONLYDIR":"c","IN_OPEN":"c","IN_Q_OVERFLOW":"c","IN_UNMOUNT":"c","IPMreq":"t","IPMreqn":"t","IPPROTO_AH":"c","IPPROTO_COMP":"c","IPPROTO_DCCP":"c","IPPROTO_DSTOPTS":"c","IPPROTO_EGP":"c","IPPROTO_ENCAP":"c","IPPROTO_ESP":"c","IPPROTO_FRAGMENT":"c","IPPROTO_GRE":"c","IPPROTO_HOPOPTS":"c","IPPROTO_ICMP":"c","IPPROTO_ICMPV6":"c","IPPROTO_IDP":"c","IPPROTO_IGMP":"c","IPPROTO_IP":"c","IPPROTO_IPIP":"c","IPPROTO_IPV6":"c","IPPROTO_MTP":"c","IPPROTO_NONE":"c","IPPROTO_PIM":"c","IPPROTO_PUP":"c","IPPROTO_RAW":"c","IPPROTO_ROUTING":"c","IPPROTO_RSVP":"c","IPPROTO_SCTP":"c","IPPROTO_TCP":"c","IPPROTO_TP":"c","IPPROTO_UDP":"c","IPPROTO_UDPLITE":"c","IPV6_2292DSTOPTS":"c","IPV6_2292HOPLIMIT":"c","IPV6_2292HOPOPTS":"c","IPV6_2292PKTINFO":"c","IPV6_2292PKTOPTIONS":"c","IPV6_2292RTHDR":"c","IPV6_ADDRFORM":"c","IPV6_ADD_MEMBERSHIP":"c","IPV6_AUTHHDR":"c","IPV6_CHECKSUM":"c","IPV6_DROP_MEMBERSHIP":"c","IPV6_DSTOPTS":"c","IPV6_HOPLIMIT":"c","IPV6_HOPOPTS":"c","IPV6_IPSEC_POLICY":"c","IPV6_JOIN_ANYCAST":"c","IPV6_JOIN_GROUP":"c","IPV6_LEAVE_ANYCAST":"c","IPV6_LEAVE_GROUP":"c","IPV6_MTU":"c","IPV6_MTU_DISCOVER":"c","IPV6_MULTICAST_HOPS":"c","IPV6_MULTICAST_IF":"c","IPV6_MULTICAST_LOOP":"c","IPV6_NEXTHOP":"c","IPV6_PKTINFO":"c","IPV6_PMTUDISC_DO":"c","IPV6_PMTUDISC_DONT":"c","IPV6_PMTUDISC_PROBE":"c","IPV6_PMTUDISC_WANT":"c","IPV6_RECVDSTOPTS":"c","IPV6_RECVERR":"c","IPV6_RECVHOPLIMIT":"c","IPV6_RECVHOPOPTS":"c","IPV6_RECVPKTINFO":"c","IPV6_RECVRTHDR":"c","IPV6_RECVTCLASS":"c","IPV6_ROUTER_ALERT":"c","IPV6_RTHDR":"c","IPV6_RTHDRDSTOPTS":"c","IPV6_RTHDR_LOOSE":"c","IPV6_RTHDR_STRICT":"c","IPV6_RTHDR_TYPE_0":"c","IPV6_RXDSTOPTS":"c","IPV6_RXHOPOPTS":"c","IPV6_TCLASS":"c","IPV6_UNICAST_HOPS":"c","IPV6_V6ONLY":"c","IPV6_XFRM_POLICY":"c","IP_ADD_MEMBERSHIP":"c","IP_ADD_SOURCE_MEMBERSHIP":"c","IP_BLOCK_SOURCE":"c","IP_DEFAULT_MULTICAST_LOOP":"c","IP_DEFAULT_MULTICAST_TTL":"c","IP_DF":"c","IP_DROP_MEMBERSHIP":"c","IP_DROP_SOURCE_MEMBERSHIP":"c","IP_FREEBIND":"c","IP_HDRINCL":"c","IP_IPSEC_POLICY":"c","IP_MAXPACKET":"c","IP_MAX_MEMBERSHIPS":"c","IP_MF":"c","IP_MINTTL":"c","IP_MSFILTER":"c","IP_MSS":"c","IP_MTU":"c","IP_MTU_DISCOVER":"c","IP_MULTICAST_IF":"c","IP_MULTICAST_LOOP":"c","IP_MULTICAST_TTL":"c","IP_OFFMASK":"c","IP_OPTIONS":"c","IP_ORIGDSTADDR":"c","IP_PASSSEC":"c","IP_PKTINFO":"c","IP_PKTOPTIONS":"c","IP_PMTUDISC":"c","IP_PMTUDISC_DO":"c","IP_PMTUDISC_DONT":"c","IP_PMTUDISC_PROBE":"c","IP_PMTUDISC_WANT":"c","IP_RECVERR":"c","IP_RECVOPTS":"c","IP_RECVORIGDSTADDR":"c","IP_RECVRETOPTS":"c","IP_RECVTOS":"c","IP_RECVTTL":"c","IP_RETOPTS":"c","IP_RF":"c","IP_ROUTER_ALERT":"c","IP_TOS":"c","IP_TRANSPARENT":"c","IP_TTL":"c","IP_UNBLOCK_SOURCE":"c","IP_XFRM_POLICY":"c","IPv6MTUInfo":"t","IPv6Mreq":"t","ISIG":"c","ISTRIP":"c","IUCLC":"c","IUTF8":"c","IXANY":"c","IXOFF":"c","IXON":"c","IfAddrmsg":"t","IfInfomsg":"t","ImplementsGetwd":"c","Inet4Pktinfo":"t","Inet6Pktinfo":"t","InotifyAddWatch":"f","InotifyEvent":"t","InotifyInit":"f","InotifyInit1":"f","InotifyRmWatch":"f","Ioperm":"f","Iopl":"f","Iovec":"t","Iovec.SetLen":"m","Kill":"f","Klogctl":"f","LINUX_REBOOT_CMD_CAD_OFF":"c","LINUX_REBOOT_CMD_CAD_ON":"c","LINUX_REBOOT_CMD_HALT":"c","LINUX_REBOOT_CMD_KEXEC":"c","LINUX_REBOOT_CMD_POWER_OFF":"c","LINUX_REBOOT_CMD_RESTART":"c","LINUX_REBOOT_CMD_RESTART2":"c","LINUX_REBOOT_CMD_SW_SUSPEND":"c","LINUX_REBOOT_MAGIC1":"c","LINUX_REBOOT_MAGIC2":"c","LOCK_EX":"c","LOCK_NB":"c","LOCK_SH":"c","LOCK_UN":"c","Lchown":"f","Linger":"t","Link":"f","Listen":"f","Listxattr":"f","LsfJump":"f","LsfSocket":"f","LsfStmt":"f","Lstat":"f","MADV_DOFORK":"c","MADV_DONTFORK":"c","MADV_DONTNEED":"c","MADV_HUGEPAGE":"c","MADV_HWPOISON":"c","MADV_MERGEABLE":"c","MADV_NOHUGEPAGE":"c","MADV_NORMAL":"c","MADV_RANDOM":"c","MADV_REMOVE":"c","MADV_SEQUENTIAL":"c","MADV_UNMERGEABLE":"c","MADV_WILLNEED":"c","MAP_32BIT":"c","MAP_ANON":"c","MAP_ANONYMOUS":"c","MAP_DENYWRITE":"c","MAP_EXECUTABLE":"c","MAP_FILE":"c","MAP_FIXED":"c","MAP_GROWSDOWN":"c","MAP_HUGETLB":"c","MAP_LOCKED":"c","MAP_NONBLOCK":"c","MAP_NORESERVE":"c","MAP_POPULATE":"c","MAP_PRIVATE":"c","MAP_SHARED":"c","MAP_STACK":"c","MAP_TYPE":"c","MCL_CURRENT":"c","MCL_FUTURE":"c","MNT_DETACH":"c","MNT_EXPIRE":"c","MNT_FORCE":"c","MSG_CMSG_CLOEXEC":"c","MSG_CONFIRM":"c","MSG_CTRUNC":"c","MSG_DONTROUTE":"c","MSG_DONTWAIT":"c","MSG_EOR":"c","MSG_ERRQUEUE":"c","MSG_FASTOPEN":"c","MSG_FIN":"c","MSG_MORE":"c","MSG_NOSIGNAL":"c","MSG_OOB":"c","MSG_PEEK":"c","MSG_PROXY":"c","MSG_RST":"c","MSG_SYN":"c","MSG_TRUNC":"c","MSG_TRYHARD":"c","MSG_WAITALL":"c","MSG_WAITFORONE":"c","MS_ACTIVE":"c","MS_ASYNC":"c","MS_BIND":"c","MS_DIRSYNC":"c","MS_INVALIDATE":"c","MS_I_VERSION":"c","MS_KERNMOUNT":"c","MS_MANDLOCK":"c","MS_MGC_MSK":"c","MS_MGC_VAL":"c","MS_MOVE":"c","MS_NOATIME":"c","MS_NODEV":"c","MS_NODIRATIME":"c","MS_NOEXEC":"c","MS_NOSUID":"c","MS_NOUSER":"c","MS_POSIXACL":"c","MS_PRIVATE":"c","MS_RDONLY":"c","MS_REC":"c","MS_RELATIME":"c","MS_REMOUNT":"c","MS_RMT_MASK":"c","MS_SHARED":"c","MS_SILENT":"c","MS_SLAVE":"c","MS_STRICTATIME":"c","MS_SYNC":"c","MS_SYNCHRONOUS":"c","MS_UNBINDABLE":"c","Madvise":"f","Mkdir":"f","Mkdirat":"f","Mkfifo":"f","Mknod":"f","Mknodat":"f","Mlock":"f","Mlockall":"f","Mmap":"f","Mount":"f","Mprotect":"f","Msghdr":"t","Msghdr.SetControllen":"m","Munlock":"f","Munlockall":"f","Munmap":"f","NAME_MAX":"c","NETLINK_ADD_MEMBERSHIP":"c","NETLINK_AUDIT":"c","NETLINK_BROADCAST_ERROR":"c","NETLINK_CONNECTOR":"c","NETLINK_DNRTMSG":"c","NETLINK_DROP_MEMBERSHIP":"c","NETLINK_ECRYPTFS":"c","NETLINK_FIB_LOOKUP":"c","NETLINK_FIREWALL":"c","NETLINK_GENERIC":"c","NETLINK_INET_DIAG":"c","NETLINK_IP6_FW":"c","NETLINK_ISCSI":"c","NETLINK_KOBJECT_UEVENT":"c","NETLINK_NETFILTER":"c","NETLINK_NFLOG":"c","NETLINK_NO_ENOBUFS":"c","NETLINK_PKTINFO":"c","NETLINK_ROUTE":"c","NETLINK_SCSITRANSPORT":"c","NETLINK_SELINUX":"c","NETLINK_UNUSED":"c","NETLINK_USERSOCK":"c","NETLINK_XFRM":"c","NLA_ALIGNTO":"c","NLA_F_NESTED":"c","NLA_F_NET_BYTEORDER":"c","NLA_HDRLEN":"c","NLMSG_ALIGNTO":"c","NLMSG_DONE":"c","NLMSG_ERROR":"c","NLMSG_HDRLEN":"c","NLMSG_MIN_TYPE":"c","NLMSG_NOOP":"c","NLMSG_OVERRUN":"c","NLM_F_ACK":"c","NLM_F_APPEND":"c","NLM_F_ATOMIC":"c","NLM_F_CREATE":"c","NLM_F_DUMP":"c","NLM_F_ECHO":"c","NLM_F_EXCL":"c","NLM_F_MATCH":"c","NLM_F_MULTI":"c","NLM_F_REPLACE":"c","NLM_F_REQUEST":"c","NLM_F_ROOT":"c","NOFLSH":"c","Nanosleep":"f","NetlinkMessage":"t","NetlinkRIB":"f","NetlinkRouteAttr":"t","NetlinkRouteRequest":"t","NlAttr":"t","NlMsgerr":"t","NlMsghdr":"t","NsecToTimespec":"f","NsecToTimeval":"f","OCRNL":"c","OFDEL":"c","OFILL":"c","OLCUC":"c","ONLCR":"c","ONLRET":"c","ONOCR":"c","OPOST":"c","O_ACCMODE":"c","O_APPEND":"c","O_ASYNC":"c","O_CLOEXEC":"c","O_CREAT":"c","O_DIRECT":"c","O_DIRECTORY":"c","O_DSYNC":"c","O_EXCL":"c","O_FSYNC":"c","O_LARGEFILE":"c","O_NDELAY":"c","O_NOATIME":"c","O_NOCTTY":"c","O_NOFOLLOW":"c","O_NONBLOCK":"c","O_RDONLY":"c","O_RDWR":"c","O_RSYNC":"c","O_SYNC":"c","O_TRUNC":"c","O_WRONLY":"c","Open":"f","Openat":"f","PACKET_ADD_MEMBERSHIP":"c","PACKET_BROADCAST":"c","PACKET_DROP_MEMBERSHIP":"c","PACKET_FASTROUTE":"c","PACKET_HOST":"c","PACKET_LOOPBACK":"c","PACKET_MR_ALLMULTI":"c","PACKET_MR_MULTICAST":"c","PACKET_MR_PROMISC":"c","PACKET_MULTICAST":"c","PACKET_OTHERHOST":"c","PACKET_OUTGOING":"c","PACKET_RECV_OUTPUT":"c","PACKET_RX_RING":"c","PACKET_STATISTICS":"c","PARENB":"c","PARMRK":"c","PARODD":"c","PENDIN":"c","PRIO_PGRP":"c","PRIO_PROCESS":"c","PRIO_USER":"c","PROT_EXEC":"c","PROT_GROWSDOWN":"c","PROT_GROWSUP":"c","PROT_NONE":"c","PROT_READ":"c","PROT_WRITE":"c","PR_CAPBSET_DROP":"c","PR_CAPBSET_READ":"c","PR_ENDIAN_BIG":"c","PR_ENDIAN_LITTLE":"c","PR_ENDIAN_PPC_LITTLE":"c","PR_FPEMU_NOPRINT":"c","PR_FPEMU_SIGFPE":"c","PR_FP_EXC_ASYNC":"c","PR_FP_EXC_DISABLED":"c","PR_FP_EXC_DIV":"c","PR_FP_EXC_INV":"c","PR_FP_EXC_NONRECOV":"c","PR_FP_EXC_OVF":"c","PR_FP_EXC_PRECISE":"c","PR_FP_EXC_RES":"c","PR_FP_EXC_SW_ENABLE":"c","PR_FP_EXC_UND":"c","PR_GET_DUMPABLE":"c","PR_GET_ENDIAN":"c","PR_GET_FPEMU":"c","PR_GET_FPEXC":"c","PR_GET_KEEPCAPS":"c","PR_GET_NAME":"c","PR_GET_PDEATHSIG":"c","PR_GET_SECCOMP":"c","PR_GET_SECUREBITS":"c","PR_GET_TIMERSLACK":"c","PR_GET_TIMING":"c","PR_GET_TSC":"c","PR_GET_UNALIGN":"c","PR_MCE_KILL":"c","PR_MCE_KILL_CLEAR":"c","PR_MCE_KILL_DEFAULT":"c","PR_MCE_KILL_EARLY":"c","PR_MCE_KILL_GET":"c","PR_MCE_KILL_LATE":"c","PR_MCE_KILL_SET":"c","PR_SET_DUMPABLE":"c","PR_SET_ENDIAN":"c","PR_SET_FPEMU":"c","PR_SET_FPEXC":"c","PR_SET_KEEPCAPS":"c","PR_SET_NAME":"c","PR_SET_PDEATHSIG":"c","PR_SET_PTRACER":"c","PR_SET_SECCOMP":"c","PR_SET_SECUREBITS":"c","PR_SET_TIMERSLACK":"c","PR_SET_TIMING":"c","PR_SET_TSC":"c","PR_SET_UNALIGN":"c","PR_TASK_PERF_EVENTS_DISABLE":"c","PR_TASK_PERF_EVENTS_ENABLE":"c","PR_TIMING_STATISTICAL":"c","PR_TIMING_TIMESTAMP":"c","PR_TSC_ENABLE":"c","PR_TSC_SIGSEGV":"c","PR_UNALIGN_NOPRINT":"c","PR_UNALIGN_SIGBUS":"c","PTRACE_ARCH_PRCTL":"c","PTRACE_ATTACH":"c","PTRACE_CONT":"c","PTRACE_DETACH":"c","PTRACE_EVENT_CLONE":"c","PTRACE_EVENT_EXEC":"c","PTRACE_EVENT_EXIT":"c","PTRACE_EVENT_FORK":"c","PTRACE_EVENT_VFORK":"c","PTRACE_EVENT_VFORK_DONE":"c","PTRACE_GETEVENTMSG":"c","PTRACE_GETFPREGS":"c","PTRACE_GETFPXREGS":"c","PTRACE_GETREGS":"c","PTRACE_GETREGSET":"c","PTRACE_GETSIGINFO":"c","PTRACE_GET_THREAD_AREA":"c","PTRACE_KILL":"c","PTRACE_OLDSETOPTIONS":"c","PTRACE_O_MASK":"c","PTRACE_O_TRACECLONE":"c","PTRACE_O_TRACEEXEC":"c","PTRACE_O_TRACEEXIT":"c","PTRACE_O_TRACEFORK":"c","PTRACE_O_TRACESYSGOOD":"c","PTRACE_O_TRACEVFORK":"c","PTRACE_O_TRACEVFORKDONE":"c","PTRACE_PEEKDATA":"c","PTRACE_PEEKTEXT":"c","PTRACE_PEEKUSR":"c","PTRACE_POKEDATA":"c","PTRACE_POKETEXT":"c","PTRACE_POKEUSR":"c","PTRACE_SETFPREGS":"c","PTRACE_SETFPXREGS":"c","PTRACE_SETOPTIONS":"c","PTRACE_SETREGS":"c","PTRACE_SETREGSET":"c","PTRACE_SETSIGINFO":"c","PTRACE_SET_THREAD_AREA":"c","PTRACE_SINGLEBLOCK":"c","PTRACE_SINGLESTEP":"c","PTRACE_SYSCALL":"c","PTRACE_SYSEMU":"c","PTRACE_SYSEMU_SINGLESTEP":"c","PTRACE_TRACEME":"c","ParseDirent":"f","ParseNetlinkMessage":"f","ParseNetlinkRouteAttr":"f","ParseSocketControlMessage":"f","ParseUnixCredentials":"f","ParseUnixRights":"f","PathMax":"c","Pause":"f","Pipe":"f","Pipe2":"f","PivotRoot":"f","Pread":"f","ProcAttr":"t","PtraceAttach":"f","PtraceCont":"f","PtraceDetach":"f","PtraceGetEventMsg":"f","PtraceGetRegs":"f","PtracePeekData":"f","PtracePeekText":"f","PtracePokeData":"f","PtracePokeText":"f","PtraceRegs":"t","PtraceRegs.PC":"m","PtraceRegs.SetPC":"m","PtraceSetOptions":"f","PtraceSetRegs":"f","PtraceSingleStep":"f","PtraceSyscall":"f","Pwrite":"f","RLIMIT_AS":"c","RLIMIT_CORE":"c","RLIMIT_CPU":"c","RLIMIT_DATA":"c","RLIMIT_FSIZE":"c","RLIMIT_NOFILE":"c","RLIMIT_STACK":"c","RLIM_INFINITY":"c","RTAX_ADVMSS":"c","RTAX_CWND":"c","RTAX_FEATURES":"c","RTAX_FEATURE_ALLFRAG":"c","RTAX_FEATURE_ECN":"c","RTAX_FEATURE_SACK":"c","RTAX_FEATURE_TIMESTAMP":"c","RTAX_HOPLIMIT":"c","RTAX_INITCWND":"c","RTAX_INITRWND":"c","RTAX_LOCK":"c","RTAX_MAX":"c","RTAX_MTU":"c","RTAX_REORDERING":"c","RTAX_RTO_MIN":"c","RTAX_RTT":"c","RTAX_RTTVAR":"c","RTAX_SSTHRESH":"c","RTAX_UNSPEC":"c","RTAX_WINDOW":"c","RTA_ALIGNTO":"c","RTA_CACHEINFO":"c","RTA_DST":"c","RTA_FLOW":"c","RTA_GATEWAY":"c","RTA_IIF":"c","RTA_MAX":"c","RTA_METRICS":"c","RTA_MULTIPATH":"c","RTA_OIF":"c","RTA_PREFSRC":"c","RTA_PRIORITY":"c","RTA_SRC":"c","RTA_TABLE":"c","RTA_UNSPEC":"c","RTCF_DIRECTSRC":"c","RTCF_DOREDIRECT":"c","RTCF_LOG":"c","RTCF_MASQ":"c","RTCF_NAT":"c","RTCF_VALVE":"c","RTF_ADDRCLASSMASK":"c","RTF_ADDRCONF":"c","RTF_ALLONLINK":"c","RTF_BROADCAST":"c","RTF_CACHE":"c","RTF_DEFAULT":"c","RTF_DYNAMIC":"c","RTF_FLOW":"c","RTF_GATEWAY":"c","RTF_HOST":"c","RTF_INTERFACE":"c","RTF_IRTT":"c","RTF_LINKRT":"c","RTF_LOCAL":"c","RTF_MODIFIED":"c","RTF_MSS":"c","RTF_MTU":"c","RTF_MULTICAST":"c","RTF_NAT":"c","RTF_NOFORWARD":"c","RTF_NONEXTHOP":"c","RTF_NOPMTUDISC":"c","RTF_POLICY":"c","RTF_REINSTATE":"c","RTF_REJECT":"c","RTF_STATIC":"c","RTF_THROW":"c","RTF_UP":"c","RTF_WINDOW":"c","RTF_XRESOLVE":"c","RTM_BASE":"c","RTM_DELACTION":"c","RTM_DELADDR":"c","RTM_DELADDRLABEL":"c","RTM_DELLINK":"c","RTM_DELNEIGH":"c","RTM_DELQDISC":"c","RTM_DELROUTE":"c","RTM_DELRULE":"c","RTM_DELTCLASS":"c","RTM_DELTFILTER":"c","RTM_F_CLONED":"c","RTM_F_EQUALIZE":"c","RTM_F_NOTIFY":"c","RTM_F_PREFIX":"c","RTM_GETACTION":"c","RTM_GETADDR":"c","RTM_GETADDRLABEL":"c","RTM_GETANYCAST":"c","RTM_GETDCB":"c","RTM_GETLINK":"c","RTM_GETMULTICAST":"c","RTM_GETNEIGH":"c","RTM_GETNEIGHTBL":"c","RTM_GETQDISC":"c","RTM_GETROUTE":"c","RTM_GETRULE":"c","RTM_GETTCLASS":"c","RTM_GETTFILTER":"c","RTM_MAX":"c","RTM_NEWACTION":"c","RTM_NEWADDR":"c","RTM_NEWADDRLABEL":"c","RTM_NEWLINK":"c","RTM_NEWNDUSEROPT":"c","RTM_NEWNEIGH":"c","RTM_NEWNEIGHTBL":"c","RTM_NEWPREFIX":"c","RTM_NEWQDISC":"c","RTM_NEWROUTE":"c","RTM_NEWRULE":"c","RTM_NEWTCLASS":"c","RTM_NEWTFILTER":"c","RTM_NR_FAMILIES":"c","RTM_NR_MSGTYPES":"c","RTM_SETDCB":"c","RTM_SETLINK":"c","RTM_SETNEIGHTBL":"c","RTNH_ALIGNTO":"c","RTNH_F_DEAD":"c","RTNH_F_ONLINK":"c","RTNH_F_PERVASIVE":"c","RTNLGRP_IPV4_IFADDR":"c","RTNLGRP_IPV4_MROUTE":"c","RTNLGRP_IPV4_ROUTE":"c","RTNLGRP_IPV4_RULE":"c","RTNLGRP_IPV6_IFADDR":"c","RTNLGRP_IPV6_IFINFO":"c","RTNLGRP_IPV6_MROUTE":"c","RTNLGRP_IPV6_PREFIX":"c","RTNLGRP_IPV6_ROUTE":"c","RTNLGRP_IPV6_RULE":"c","RTNLGRP_LINK":"c","RTNLGRP_ND_USEROPT":"c","RTNLGRP_NEIGH":"c","RTNLGRP_NONE":"c","RTNLGRP_NOTIFY":"c","RTNLGRP_TC":"c","RTN_ANYCAST":"c","RTN_BLACKHOLE":"c","RTN_BROADCAST":"c","RTN_LOCAL":"c","RTN_MAX":"c","RTN_MULTICAST":"c","RTN_NAT":"c","RTN_PROHIBIT":"c","RTN_THROW":"c","RTN_UNICAST":"c","RTN_UNREACHABLE":"c","RTN_UNSPEC":"c","RTN_XRESOLVE":"c","RTPROT_BIRD":"c","RTPROT_BOOT":"c","RTPROT_DHCP":"c","RTPROT_DNROUTED":"c","RTPROT_GATED":"c","RTPROT_KERNEL":"c","RTPROT_MRT":"c","RTPROT_NTK":"c","RTPROT_RA":"c","RTPROT_REDIRECT":"c","RTPROT_STATIC":"c","RTPROT_UNSPEC":"c","RTPROT_XORP":"c","RTPROT_ZEBRA":"c","RT_CLASS_DEFAULT":"c","RT_CLASS_LOCAL":"c","RT_CLASS_MAIN":"c","RT_CLASS_MAX":"c","RT_CLASS_UNSPEC":"c","RT_SCOPE_HOST":"c","RT_SCOPE_LINK":"c","RT_SCOPE_NOWHERE":"c","RT_SCOPE_SITE":"c","RT_SCOPE_UNIVERSE":"c","RT_TABLE_COMPAT":"c","RT_TABLE_DEFAULT":"c","RT_TABLE_LOCAL":"c","RT_TABLE_MAIN":"c","RT_TABLE_MAX":"c","RT_TABLE_UNSPEC":"c","RUSAGE_CHILDREN":"c","RUSAGE_SELF":"c","RUSAGE_THREAD":"c","RawConn":"t","RawSockaddr":"t","RawSockaddrAny":"t","RawSockaddrInet4":"t","RawSockaddrInet6":"t","RawSockaddrLinklayer":"t","RawSockaddrNetlink":"t","RawSockaddrUnix":"t","RawSyscall":"f","RawSyscall6":"f","Read":"f","ReadDirent":"f","Readlink":"f","Reboot":"f","Recvfrom":"f","Recvmsg":"f","Removexattr":"f","Rename":"f","Renameat":"f","Rlimit":"t","Rmdir":"f","RtAttr":"t","RtGenmsg":"t","RtMsg":"t","RtNexthop":"t","Rusage":"t","SCM_CREDENTIALS":"c","SCM_RIGHTS":"c","SCM_TIMESTAMP":"c","SCM_TIMESTAMPING":"c","SCM_TIMESTAMPNS":"c","SHUT_RD":"c","SHUT_RDWR":"c","SHUT_WR":"c","SIGABRT":"c","SIGALRM":"c","SIGBUS":"c","SIGCHLD":"c","SIGCLD":"c","SIGCONT":"c","SIGFPE":"c","SIGHUP":"c","SIGILL":"c","SIGINT":"c","SIGIO":"c","SIGIOT":"c","SIGKILL":"c","SIGPIPE":"c","SIGPOLL":"c","SIGPROF":"c","SIGPWR":"c","SIGQUIT":"c","SIGSEGV":"c","SIGSTKFLT":"c","SIGSTOP":"c","SIGSYS":"c","SIGTERM":"c","SIGTRAP":"c","SIGTSTP":"c","SIGTTIN":"c","SIGTTOU":"c","SIGUNUSED":"c","SIGURG":"c","SIGUSR1":"c","SIGUSR2":"c","SIGVTALRM":"c","SIGWINCH":"c","SIGXCPU":"c","SIGXFSZ":"c","SIOCADDDLCI":"c","SIOCADDMULTI":"c","SIOCADDRT":"c","SIOCATMARK":"c","SIOCDARP":"c","SIOCDELDLCI":"c","SIOCDELMULTI":"c","SIOCDELRT":"c","SIOCDEVPRIVATE":"c","SIOCDIFADDR":"c","SIOCDRARP":"c","SIOCGARP":"c","SIOCGIFADDR":"c","SIOCGIFBR":"c","SIOCGIFBRDADDR":"c","SIOCGIFCONF":"c","SIOCGIFCOUNT":"c","SIOCGIFDSTADDR":"c","SIOCGIFENCAP":"c","SIOCGIFFLAGS":"c","SIOCGIFHWADDR":"c","SIOCGIFINDEX":"c","SIOCGIFMAP":"c","SIOCGIFMEM":"c","SIOCGIFMETRIC":"c","SIOCGIFMTU":"c","SIOCGIFNAME":"c","SIOCGIFNETMASK":"c","SIOCGIFPFLAGS":"c","SIOCGIFSLAVE":"c","SIOCGIFTXQLEN":"c","SIOCGPGRP":"c","SIOCGRARP":"c","SIOCGSTAMP":"c","SIOCGSTAMPNS":"c","SIOCPROTOPRIVATE":"c","SIOCRTMSG":"c","SIOCSARP":"c","SIOCSIFADDR":"c","SIOCSIFBR":"c","SIOCSIFBRDADDR":"c","SIOCSIFDSTADDR":"c","SIOCSIFENCAP":"c","SIOCSIFFLAGS":"c","SIOCSIFHWADDR":"c","SIOCSIFHWBROADCAST":"c","SIOCSIFLINK":"c","SIOCSIFMAP":"c","SIOCSIFMEM":"c","SIOCSIFMETRIC":"c","SIOCSIFMTU":"c","SIOCSIFNAME":"c","SIOCSIFNETMASK":"c","SIOCSIFPFLAGS":"c","SIOCSIFSLAVE":"c","SIOCSIFTXQLEN":"c","SIOCSPGRP":"c","SIOCSRARP":"c","SOCK_CLOEXEC":"c","SOCK_DCCP":"c","SOCK_DGRAM":"c","SOCK_NONBLOCK":"c","SOCK_PACKET":"c","SOCK_RAW":"c","SOCK_RDM":"c","SOCK_SEQPACKET":"c","SOCK_STREAM":"c","SOL_AAL":"c","SOL_ATM":"c","SOL_DECNET":"c","SOL_ICMPV6":"c","SOL_IP":"c","SOL_IPV6":"c","SOL_IRDA":"c","SOL_PACKET":"c","SOL_RAW":"c","SOL_SOCKET":"c","SOL_TCP":"c","SOL_X25":"c","SOMAXCONN":"c","SO_ACCEPTCONN":"c","SO_ATTACH_FILTER":"c","SO_BINDTODEVICE":"c","SO_BROADCAST":"c","SO_BSDCOMPAT":"c","SO_DEBUG":"c","SO_DETACH_FILTER":"c","SO_DOMAIN":"c","SO_DONTROUTE":"c","SO_ERROR":"c","SO_KEEPALIVE":"c","SO_LINGER":"c","SO_MARK":"c","SO_NO_CHECK":"c","SO_OOBINLINE":"c","SO_PASSCRED":"c","SO_PASSSEC":"c","SO_PEERCRED":"c","SO_PEERNAME":"c","SO_PEERSEC":"c","SO_PRIORITY":"c","SO_PROTOCOL":"c","SO_RCVBUF":"c","SO_RCVBUFFORCE":"c","SO_RCVLOWAT":"c","SO_RCVTIMEO":"c","SO_REUSEADDR":"c","SO_RXQ_OVFL":"c","SO_SECURITY_AUTHENTICATION":"c","SO_SECURITY_ENCRYPTION_NETWORK":"c","SO_SECURITY_ENCRYPTION_TRANSPORT":"c","SO_SNDBUF":"c","SO_SNDBUFFORCE":"c","SO_SNDLOWAT":"c","SO_SNDTIMEO":"c","SO_TIMESTAMP":"c","SO_TIMESTAMPING":"c","SO_TIMESTAMPNS":"c","SO_TYPE":"c","SYS_ACCEPT":"c","SYS_ACCEPT4":"c","SYS_ACCESS":"c","SYS_ACCT":"c","SYS_ADD_KEY":"c","SYS_ADJTIMEX":"c","SYS_AFS_SYSCALL":"c","SYS_ALARM":"c","SYS_ARCH_PRCTL":"c","SYS_BIND":"c","SYS_BRK":"c","SYS_CAPGET":"c","SYS_CAPSET":"c","SYS_CHDIR":"c","SYS_CHMOD":"c","SYS_CHOWN":"c","SYS_CHROOT":"c","SYS_CLOCK_GETRES":"c","SYS_CLOCK_GETTIME":"c","SYS_CLOCK_NANOSLEEP":"c","SYS_CLOCK_SETTIME":"c","SYS_CLONE":"c","SYS_CLOSE":"c","SYS_CONNECT":"c","SYS_CREAT":"c","SYS_CREATE_MODULE":"c","SYS_DELETE_MODULE":"c","SYS_DUP":"c","SYS_DUP2":"c","SYS_DUP3":"c","SYS_EPOLL_CREATE":"c","SYS_EPOLL_CREATE1":"c","SYS_EPOLL_CTL":"c","SYS_EPOLL_CTL_OLD":"c","SYS_EPOLL_PWAIT":"c","SYS_EPOLL_WAIT":"c","SYS_EPOLL_WAIT_OLD":"c","SYS_EVENTFD":"c","SYS_EVENTFD2":"c","SYS_EXECVE":"c","SYS_EXIT":"c","SYS_EXIT_GROUP":"c","SYS_FACCESSAT":"c","SYS_FADVISE64":"c","SYS_FALLOCATE":"c","SYS_FANOTIFY_INIT":"c","SYS_FANOTIFY_MARK":"c","SYS_FCHDIR":"c","SYS_FCHMOD":"c","SYS_FCHMODAT":"c","SYS_FCHOWN":"c","SYS_FCHOWNAT":"c","SYS_FCNTL":"c","SYS_FDATASYNC":"c","SYS_FGETXATTR":"c","SYS_FLISTXATTR":"c","SYS_FLOCK":"c","SYS_FORK":"c","SYS_FREMOVEXATTR":"c","SYS_FSETXATTR":"c","SYS_FSTAT":"c","SYS_FSTATFS":"c","SYS_FSYNC":"c","SYS_FTRUNCATE":"c","SYS_FUTEX":"c","SYS_FUTIMESAT":"c","SYS_GETCWD":"c","SYS_GETDENTS":"c","SYS_GETDENTS64":"c","SYS_GETEGID":"c","SYS_GETEUID":"c","SYS_GETGID":"c","SYS_GETGROUPS":"c","SYS_GETITIMER":"c","SYS_GETPEERNAME":"c","SYS_GETPGID":"c","SYS_GETPGRP":"c","SYS_GETPID":"c","SYS_GETPMSG":"c","SYS_GETPPID":"c","SYS_GETPRIORITY":"c","SYS_GETRESGID":"c","SYS_GETRESUID":"c","SYS_GETRLIMIT":"c","SYS_GETRUSAGE":"c","SYS_GETSID":"c","SYS_GETSOCKNAME":"c","SYS_GETSOCKOPT":"c","SYS_GETTID":"c","SYS_GETTIMEOFDAY":"c","SYS_GETUID":"c","SYS_GETXATTR":"c","SYS_GET_KERNEL_SYMS":"c","SYS_GET_MEMPOLICY":"c","SYS_GET_ROBUST_LIST":"c","SYS_GET_THREAD_AREA":"c","SYS_INIT_MODULE":"c","SYS_INOTIFY_ADD_WATCH":"c","SYS_INOTIFY_INIT":"c","SYS_INOTIFY_INIT1":"c","SYS_INOTIFY_RM_WATCH":"c","SYS_IOCTL":"c","SYS_IOPERM":"c","SYS_IOPL":"c","SYS_IOPRIO_GET":"c","SYS_IOPRIO_SET":"c","SYS_IO_CANCEL":"c","SYS_IO_DESTROY":"c","SYS_IO_GETEVENTS":"c","SYS_IO_SETUP":"c","SYS_IO_SUBMIT":"c","SYS_KEXEC_LOAD":"c","SYS_KEYCTL":"c","SYS_KILL":"c","SYS_LCHOWN":"c","SYS_LGETXATTR":"c","SYS_LINK":"c","SYS_LINKAT":"c","SYS_LISTEN":"c","SYS_LISTXATTR":"c","SYS_LLISTXATTR":"c","SYS_LOOKUP_DCOOKIE":"c","SYS_LREMOVEXATTR":"c","SYS_LSEEK":"c","SYS_LSETXATTR":"c","SYS_LSTAT":"c","SYS_MADVISE":"c","SYS_MBIND":"c","SYS_MIGRATE_PAGES":"c","SYS_MINCORE":"c","SYS_MKDIR":"c","SYS_MKDIRAT":"c","SYS_MKNOD":"c","SYS_MKNODAT":"c","SYS_MLOCK":"c","SYS_MLOCKALL":"c","SYS_MMAP":"c","SYS_MODIFY_LDT":"c","SYS_MOUNT":"c","SYS_MOVE_PAGES":"c","SYS_MPROTECT":"c","SYS_MQ_GETSETATTR":"c","SYS_MQ_NOTIFY":"c","SYS_MQ_OPEN":"c","SYS_MQ_TIMEDRECEIVE":"c","SYS_MQ_TIMEDSEND":"c","SYS_MQ_UNLINK":"c","SYS_MREMAP":"c","SYS_MSGCTL":"c","SYS_MSGGET":"c","SYS_MSGRCV":"c","SYS_MSGSND":"c","SYS_MSYNC":"c","SYS_MUNLOCK":"c","SYS_MUNLOCKALL":"c","SYS_MUNMAP":"c","SYS_NANOSLEEP":"c","SYS_NEWFSTATAT":"c","SYS_NFSSERVCTL":"c","SYS_OPEN":"c","SYS_OPENAT":"c","SYS_PAUSE":"c","SYS_PERF_EVENT_OPEN":"c","SYS_PERSONALITY":"c","SYS_PIPE":"c","SYS_PIPE2":"c","SYS_PIVOT_ROOT":"c","SYS_POLL":"c","SYS_PPOLL":"c","SYS_PRCTL":"c","SYS_PREAD64":"c","SYS_PREADV":"c","SYS_PRLIMIT64":"c","SYS_PSELECT6":"c","SYS_PTRACE":"c","SYS_PUTPMSG":"c","SYS_PWRITE64":"c","SYS_PWRITEV":"c","SYS_QUERY_MODULE":"c","SYS_QUOTACTL":"c","SYS_READ":"c","SYS_READAHEAD":"c","SYS_READLINK":"c","SYS_READLINKAT":"c","SYS_READV":"c","SYS_REBOOT":"c","SYS_RECVFROM":"c","SYS_RECVMMSG":"c","SYS_RECVMSG":"c","SYS_REMAP_FILE_PAGES":"c","SYS_REMOVEXATTR":"c","SYS_RENAME":"c","SYS_RENAMEAT":"c","SYS_REQUEST_KEY":"c","SYS_RESTART_SYSCALL":"c","SYS_RMDIR":"c","SYS_RT_SIGACTION":"c","SYS_RT_SIGPENDING":"c","SYS_RT_SIGPROCMASK":"c","SYS_RT_SIGQUEUEINFO":"c","SYS_RT_SIGRETURN":"c","SYS_RT_SIGSUSPEND":"c","SYS_RT_SIGTIMEDWAIT":"c","SYS_RT_TGSIGQUEUEINFO":"c","SYS_SCHED_GETAFFINITY":"c","SYS_SCHED_GETPARAM":"c","SYS_SCHED_GETSCHEDULER":"c","SYS_SCHED_GET_PRIORITY_MAX":"c","SYS_SCHED_GET_PRIORITY_MIN":"c","SYS_SCHED_RR_GET_INTERVAL":"c","SYS_SCHED_SETAFFINITY":"c","SYS_SCHED_SETPARAM":"c","SYS_SCHED_SETSCHEDULER":"c","SYS_SCHED_YIELD":"c","SYS_SECURITY":"c","SYS_SELECT":"c","SYS_SEMCTL":"c","SYS_SEMGET":"c","SYS_SEMOP":"c","SYS_SEMTIMEDOP":"c","SYS_SENDFILE":"c","SYS_SENDMSG":"c","SYS_SENDTO":"c","SYS_SETDOMAINNAME":"c","SYS_SETFSGID":"c","SYS_SETFSUID":"c","SYS_SETGID":"c","SYS_SETGROUPS":"c","SYS_SETHOSTNAME":"c","SYS_SETITIMER":"c","SYS_SETPGID":"c","SYS_SETPRIORITY":"c","SYS_SETREGID":"c","SYS_SETRESGID":"c","SYS_SETRESUID":"c","SYS_SETREUID":"c","SYS_SETRLIMIT":"c","SYS_SETSID":"c","SYS_SETSOCKOPT":"c","SYS_SETTIMEOFDAY":"c","SYS_SETUID":"c","SYS_SETXATTR":"c","SYS_SET_MEMPOLICY":"c","SYS_SET_ROBUST_LIST":"c","SYS_SET_THREAD_AREA":"c","SYS_SET_TID_ADDRESS":"c","SYS_SHMAT":"c","SYS_SHMCTL":"c","SYS_SHMDT":"c","SYS_SHMGET":"c","SYS_SHUTDOWN":"c","SYS_SIGALTSTACK":"c","SYS_SIGNALFD":"c","SYS_SIGNALFD4":"c","SYS_SOCKET":"c","SYS_SOCKETPAIR":"c","SYS_SPLICE":"c","SYS_STAT":"c","SYS_STATFS":"c","SYS_SWAPOFF":"c","SYS_SWAPON":"c","SYS_SYMLINK":"c","SYS_SYMLINKAT":"c","SYS_SYNC":"c","SYS_SYNC_FILE_RANGE":"c","SYS_SYSFS":"c","SYS_SYSINFO":"c","SYS_SYSLOG":"c","SYS_TEE":"c","SYS_TGKILL":"c","SYS_TIME":"c","SYS_TIMERFD_CREATE":"c","SYS_TIMERFD_GETTIME":"c","SYS_TIMERFD_SETTIME":"c","SYS_TIMER_CREATE":"c","SYS_TIMER_DELETE":"c","SYS_TIMER_GETOVERRUN":"c","SYS_TIMER_GETTIME":"c","SYS_TIMER_SETTIME":"c","SYS_TIMES":"c","SYS_TKILL":"c","SYS_TRUNCATE":"c","SYS_TUXCALL":"c","SYS_UMASK":"c","SYS_UMOUNT2":"c","SYS_UNAME":"c","SYS_UNLINK":"c","SYS_UNLINKAT":"c","SYS_UNSHARE":"c","SYS_USELIB":"c","SYS_USTAT":"c","SYS_UTIME":"c","SYS_UTIMENSAT":"c","SYS_UTIMES":"c","SYS_VFORK":"c","SYS_VHANGUP":"c","SYS_VMSPLICE":"c","SYS_VSERVER":"c","SYS_WAIT4":"c","SYS_WAITID":"c","SYS_WRITE":"c","SYS_WRITEV":"c","SYS__SYSCTL":"c","S_BLKSIZE":"c","S_IEXEC":"c","S_IFBLK":"c","S_IFCHR":"c","S_IFDIR":"c","S_IFIFO":"c","S_IFLNK":"c","S_IFMT":"c","S_IFREG":"c","S_IFSOCK":"c","S_IREAD":"c","S_IRGRP":"c","S_IROTH":"c","S_IRUSR":"c","S_IRWXG":"c","S_IRWXO":"c","S_IRWXU":"c","S_ISGID":"c","S_ISUID":"c","S_ISVTX":"c","S_IWGRP":"c","S_IWOTH":"c","S_IWRITE":"c","S_IWUSR":"c","S_IXGRP":"c","S_IXOTH":"c","S_IXUSR":"c","Seek":"f","Select":"f","Sendfile":"f","Sendmsg":"f","SendmsgN":"f","Sendto":"f","SetLsfPromisc":"f","SetNonblock":"f","Setdomainname":"f","Setegid":"f","Setenv":"f","Seteuid":"f","Setfsgid":"f","Setfsuid":"f","Setgid":"f","Setgroups":"f","Sethostname":"f","Setpgid":"f","Setpriority":"f","Setregid":"f","Setresgid":"f","Setresuid":"f","Setreuid":"f","Setrlimit":"f","Setsid":"f","SetsockoptByte":"f","SetsockoptICMPv6Filter":"f","SetsockoptIPMreq":"f","SetsockoptIPMreqn":"f","SetsockoptIPv6Mreq":"f","SetsockoptInet4Addr":"f","SetsockoptInt":"f","SetsockoptLinger":"f","SetsockoptString":"f","SetsockoptTimeval":"f","Settimeofday":"f","Setuid":"f","Setxattr":"f","Shutdown":"f","Signal":"t","Signal.Signal":"m","Signal.String":"m","SizeofCmsghdr":"c","SizeofICMPv6Filter":"c","SizeofIPMreq":"c","SizeofIPMreqn":"c","SizeofIPv6MTUInfo":"c","SizeofIPv6Mreq":"c","SizeofIfAddrmsg":"c","SizeofIfInfomsg":"c","SizeofInet4Pktinfo":"c","SizeofInet6Pktinfo":"c","SizeofInotifyEvent":"c","SizeofLinger":"c","SizeofMsghdr":"c","SizeofNlAttr":"c","SizeofNlMsgerr":"c","SizeofNlMsghdr":"c","SizeofRtAttr":"c","SizeofRtGenmsg":"c","SizeofRtMsg":"c","SizeofRtNexthop":"c","SizeofSockFilter":"c","SizeofSockFprog":"c","SizeofSockaddrAny":"c","SizeofSockaddrInet4":"c","SizeofSockaddrInet6":"c","SizeofSockaddrLinklayer":"c","SizeofSockaddrNetlink":"c","SizeofSockaddrUnix":"c","SizeofTCPInfo":"c","SizeofUcred":"c","SlicePtrFromStrings":"f","SockFilter":"t","SockFprog":"t","Sockaddr":"t","SockaddrInet4":"t","SockaddrInet6":"t","SockaddrLinklayer":"t","SockaddrNetlink":"t","SockaddrUnix":"t","Socket":"f","SocketControlMessage":"t","SocketDisableIPv6":"v","Socketpair":"f","Splice":"f","StartProcess":"f","Stat":"f","Stat_t":"t","Statfs":"f","Statfs_t":"t","Stderr":"v","Stdin":"v","Stdout":"v","StringBytePtr":"f","StringByteSlice":"f","StringSlicePtr":"f","Symlink":"f","Sync":"f","SyncFileRange":"f","SysProcAttr":"t","SysProcIDMap":"t","Syscall":"f","Syscall6":"f","Sysinfo":"f","Sysinfo_t":"t","TCGETS":"c","TCIFLUSH":"c","TCIOFLUSH":"c","TCOFLUSH":"c","TCPInfo":"t","TCP_CONGESTION":"c","TCP_CORK":"c","TCP_DEFER_ACCEPT":"c","TCP_INFO":"c","TCP_KEEPCNT":"c","TCP_KEEPIDLE":"c","TCP_KEEPINTVL":"c","TCP_LINGER2":"c","TCP_MAXSEG":"c","TCP_MAXWIN":"c","TCP_MAX_WINSHIFT":"c","TCP_MD5SIG":"c","TCP_MD5SIG_MAXKEYLEN":"c","TCP_MSS":"c","TCP_NODELAY":"c","TCP_QUICKACK":"c","TCP_SYNCNT":"c","TCP_WINDOW_CLAMP":"c","TCSETS":"c","TIOCCBRK":"c","TIOCCONS":"c","TIOCEXCL":"c","TIOCGDEV":"c","TIOCGETD":"c","TIOCGICOUNT":"c","TIOCGLCKTRMIOS":"c","TIOCGPGRP":"c","TIOCGPTN":"c","TIOCGRS485":"c","TIOCGSERIAL":"c","TIOCGSID":"c","TIOCGSOFTCAR":"c","TIOCGWINSZ":"c","TIOCINQ":"c","TIOCLINUX":"c","TIOCMBIC":"c","TIOCMBIS":"c","TIOCMGET":"c","TIOCMIWAIT":"c","TIOCMSET":"c","TIOCM_CAR":"c","TIOCM_CD":"c","TIOCM_CTS":"c","TIOCM_DSR":"c","TIOCM_DTR":"c","TIOCM_LE":"c","TIOCM_RI":"c","TIOCM_RNG":"c","TIOCM_RTS":"c","TIOCM_SR":"c","TIOCM_ST":"c","TIOCNOTTY":"c","TIOCNXCL":"c","TIOCOUTQ":"c","TIOCPKT":"c","TIOCPKT_DATA":"c","TIOCPKT_DOSTOP":"c","TIOCPKT_FLUSHREAD":"c","TIOCPKT_FLUSHWRITE":"c","TIOCPKT_IOCTL":"c","TIOCPKT_NOSTOP":"c","TIOCPKT_START":"c","TIOCPKT_STOP":"c","TIOCSBRK":"c","TIOCSCTTY":"c","TIOCSERCONFIG":"c","TIOCSERGETLSR":"c","TIOCSERGETMULTI":"c","TIOCSERGSTRUCT":"c","TIOCSERGWILD":"c","TIOCSERSETMULTI":"c","TIOCSERSWILD":"c","TIOCSER_TEMT":"c","TIOCSETD":"c","TIOCSIG":"c","TIOCSLCKTRMIOS":"c","TIOCSPGRP":"c","TIOCSPTLCK":"c","TIOCSRS485":"c","TIOCSSERIAL":"c","TIOCSSOFTCAR":"c","TIOCSTI":"c","TIOCSWINSZ":"c","TOSTOP":"c","TUNATTACHFILTER":"c","TUNDETACHFILTER":"c","TUNGETFEATURES":"c","TUNGETIFF":"c","TUNGETSNDBUF":"c","TUNGETVNETHDRSZ":"c","TUNSETDEBUG":"c","TUNSETGROUP":"c","TUNSETIFF":"c","TUNSETLINK":"c","TUNSETNOCSUM":"c","TUNSETOFFLOAD":"c","TUNSETOWNER":"c","TUNSETPERSIST":"c","TUNSETSNDBUF":"c","TUNSETTXFILTER":"c","TUNSETVNETHDRSZ":"c","Tee":"f","Termios":"t","Tgkill":"f","Time":"f","Time_t":"t","Times":"f","Timespec":"t","Timespec.Nano":"m","Timespec.Unix":"m","TimespecToNsec":"f","Timeval":"t","Timeval.Nano":"m","Timeval.Unix":"m","TimevalToNsec":"f","Timex":"t","Tms":"t","Truncate":"f","Ucred":"t","Umask":"f","Uname":"f","UnixCredentials":"f","UnixRights":"f","Unlink":"f","Unlinkat":"f","Unmount":"f","Unsetenv":"f","Unshare":"f","Ustat":"f","Ustat_t":"t","Utimbuf":"t","Utime":"f","Utimes":"f","UtimesNano":"f","Utsname":"t","VDISCARD":"c","VEOF":"c","VEOL":"c","VEOL2":"c","VERASE":"c","VINTR":"c","VKILL":"c","VLNEXT":"c","VMIN":"c","VQUIT":"c","VREPRINT":"c","VSTART":"c","VSTOP":"c","VSUSP":"c","VSWTC":"c","VTIME":"c","VWERASE":"c","WALL":"c","WCLONE":"c","WCONTINUED":"c","WEXITED":"c","WNOHANG":"c","WNOTHREAD":"c","WNOWAIT":"c","WORDSIZE":"c","WSTOPPED":"c","WUNTRACED":"c","Wait4":"f","WaitStatus":"t","WaitStatus.Continued":"m","WaitStatus.CoreDump":"m","WaitStatus.ExitStatus":"m","WaitStatus.Exited":"m","WaitStatus.Signal":"m","WaitStatus.Signaled":"m","WaitStatus.StopSignal":"m","WaitStatus.Stopped":"m","WaitStatus.TrapCause":"m","Write":"f","XCASE":"c"}},"testing":{"path":"testing","name":"testing","symbols":{"AllocsPerRun":"f","B":"t","B.Elapsed":"m","B.Loop":"m","B.ReportAllocs":"m","B.ReportMetric":"m","B.ResetTimer":"m","B.Run":"m","B.RunParallel":"m","B.SetBytes":"m","B.SetParallelism":"m","B.StartTimer":"m","B.StopTimer":"m","Benchmark":"f","BenchmarkResult":"t","BenchmarkResult.AllocedBytesPerOp":"m","BenchmarkResult.AllocsPerOp":"m","BenchmarkResult.MemString":"m","BenchmarkResult.NsPerOp":"m","BenchmarkResult.String":"m","Cover":"t","CoverBlock":"t","CoverMode":"f","Coverage":"f","F":"t","F.Add":"m","F.Fail":"m","F.Fuzz":"m","F.Helper":"m","F.Skipped":"m","Init":"f","InternalBenchmark":"t","InternalExample":"t","InternalFuzzTarget":"t","InternalTest":"t","M":"t","M.Run":"m","Main":"f","MainStart":"f","PB":"t","PB.Next":"m","RegisterCover":"f","RunBenchmarks":"f","RunExamples":"f","RunTests":"f","Short":"f","T":"t","T.Chdir":"m","T.Deadline":"m","T.Parallel":"m","T.Run":"m","T.Setenv":"m","TB":"t","Testing":"f","Verbose":"f"}},"testing/fstest":{"path":"testing/fstest","name":"fstest","symbols":{"MapFS":"t","MapFS.Glob":"m","MapFS.Lstat":"m","MapFS.Open":"m","MapFS.ReadDir":"m","MapFS.ReadFile":"m","MapFS.ReadLink":"m","MapFS.Stat":"m","MapFS.Sub":"m","MapFile":"t","TestFS":"f"}},"testing/iotest":{"path":"testing/iotest","name":"iotest","symbols":{"DataErrReader":"f","ErrReader":"f","ErrTimeout":"v","HalfReader":"f","NewReadLogger":"f","NewWriteLogger":"f","OneByteReader":"f","TestReader":"f","TimeoutReader":"f","TruncateWriter":"f"}},"testing/quick":{"path":"testing/quick","name":"quick","symbols":{"Check":"f","CheckEqual":"f","CheckEqualError":"t","CheckEqualError.Error":"m","CheckError":"t","CheckError.Error":"m","Config":"t","Generator":"t","SetupError":"t","SetupError.Error":"m","Value":"f"}},"testing/slogtest":{"path":"testing/slogtest","name":"slogtest","symbols":{"Run":"f","TestHandler":"f"}},"testing/synctest":{"path":"testing/synctest","name":"synctest","symbols":{"Test":"f","Wait":"f"}},"text/scanner":{"path":"text/scanner","name":"scanner","symbols":{"Char":"c","Comment":"c","EOF":"c","Float":"c","GoTokens":"c","GoWhitespace":"c","Ident":"c","Int":"c","Position":"t","Position.IsValid":"m","Position.String":"m","RawString":"c","ScanChars":"c","ScanComments":"c","ScanFloats":"c","ScanIdents":"c","ScanInts":"c","ScanRawStrings":"c","ScanStrings":"c","Scanner":"t","Scanner.Init":"m","Scanner.Next":"m","Scanner.Peek":"m","Scanner.Pos":"m","Scanner.Scan":"m","Scanner.TokenText":"m","SkipComments":"c","String":"c","TokenString":"f"}},"text/tabwriter":{"path":"text/tabwriter","name":"tabwriter","symbols":{"AlignRight":"c","Debug":"c","DiscardEmptyColumns":"c","Escape":"c","FilterHTML":"c","NewWriter":"f","StripEscape":"c","TabIndent":"c","Writer":"t","Writer.Flush":"m","Writer.Init":"m","Writer.Write":"m"}},"text/template":{"path":"text/template","name":"template","symbols":{"ExecError":"t","ExecError.Error":"m","ExecError.Unwrap":"m","FuncMap":"t","HTMLEscape":"f","HTMLEscapeString":"f","HTMLEscaper":"f","IsTrue":"f","JSEscape":"f","JSEscapeString":"f","JSEscaper":"f","Must":"f","New":"f","ParseFS":"f","ParseFiles":"f","ParseGlob":"f","Template":"t","Template.AddParseTree":"m","Template.Clone":"m","Template.DefinedTemplates":"m","Template.Delims":"m","Template.Execute":"m","Template.ExecuteTemplate":"m","Template.Funcs":"m","Template.Lookup":"m","Template.Name":"m","Template.New":"m","Template.Option":"m","Template.Parse":"m","Template.ParseFS":"m","Template.ParseFiles":"m","Template.ParseGlob":"m","Template.Templates":"m","URLQueryEscaper":"f"}},"text/template/parse":{"path":"text/template/parse","name":"parse","symbols":{"ActionNode":"t","ActionNode.Copy":"m","ActionNode.String":"m","BoolNode":"t","BoolNode.Copy":"m","BoolNode.String":"m","BranchNode":"t","BranchNode.Copy":"m","BranchNode.String":"m","BreakNode":"t","BreakNode.Copy":"m","BreakNode.String":"m","ChainNode":"t","ChainNode.Add":"m","ChainNode.Copy":"m","ChainNode.String":"m","CommandNode":"t","CommandNode.Copy":"m","CommandNode.String":"m","CommentNode":"t","CommentNode.Copy":"m","CommentNode.String":"m","ContinueNode":"t","ContinueNode.Copy":"m","ContinueNode.String":"m","DotNode":"t","DotNode.Copy":"m","DotNode.String":"m","DotNode.Type":"m","FieldNode":"t","FieldNode.Copy":"m","FieldNode.String":"m","IdentifierNode":"t","IdentifierNode.Copy":"m","IdentifierNode.SetPos":"m","IdentifierNode.SetTree":"m","IdentifierNode.String":"m","IfNode":"t","IfNode.Copy":"m","IsEmptyTree":"f","ListNode":"t","ListNode.Copy":"m","ListNode.CopyList":"m","ListNode.String":"m","Mode":"t","New":"f","NewIdentifier":"f","NilNode":"t","NilNode.Copy":"m","NilNode.String":"m","NilNode.Type":"m","Node":"t","NodeAction":"c","NodeBool":"c","NodeBreak":"c","NodeChain":"c","NodeCommand":"c","NodeComment":"c","NodeContinue":"c","NodeDot":"c","NodeField":"c","NodeIdentifier":"c","NodeIf":"c","NodeList":"c","NodeNil":"c","NodeNumber":"c","NodePipe":"c","NodeRange":"c","NodeString":"c","NodeTemplate":"c","NodeText":"c","NodeType":"t","NodeType.Type":"m","NodeVariable":"c","NodeWith":"c","NumberNode":"t","NumberNode.Copy":"m","NumberNode.String":"m","Parse":"f","ParseComments":"c","PipeNode":"t","PipeNode.Copy":"m","PipeNode.CopyPipe":"m","PipeNode.String":"m","Pos":"t","Pos.Position":"m","RangeNode":"t","RangeNode.Copy":"m","SkipFuncCheck":"c","StringNode":"t","StringNode.Copy":"m","StringNode.String":"m","TemplateNode":"t","TemplateNode.Copy":"m","TemplateNode.String":"m","TextNode":"t","TextNode.Copy":"m","TextNode.String":"m","Tree":"t","Tree.Copy":"m","Tree.ErrorContext":"m","Tree.Parse":"m","VariableNode":"t","VariableNode.Copy":"m","VariableNode.String":"m","WithNode":"t","WithNode.Copy":"m"}},"time":{"path":"time","name":"time","symbols":{"ANSIC":"c","After":"f","AfterFunc":"f","April":"c","August":"c","Date":"f","DateOnly":"c","DateTime":"c","December":"c","Duration":"t","Duration.Abs":"m","Duration.Hours":"m","Duration.Microseconds":"m","Duration.Milliseconds":"m","Duration.Minutes":"m","Duration.Nanoseconds":"m","Duration.Round":"m","Duration.Seconds":"m","Duration.String":"m","Duration.Truncate":"m","February":"c","FixedZone":"f","Friday":"c","Hour":"c","January":"c","July":"c","June":"c","Kitchen":"c","Layout":"c","LoadLocation":"f","LoadLocationFromTZData":"f","Local":"v","Location":"t","Location.String":"m","March":"c","May":"c","Microsecond":"c","Millisecond":"c","Minute":"c","Monday":"c","Month":"t","Month.String":"m","Nanosecond":"c","NewTicker":"f","NewTimer":"f","November":"c","Now":"f","October":"c","Parse":"f","ParseDuration":"f","ParseError":"t","ParseError.Error":"m","ParseInLocation":"f","RFC1123":"c","RFC1123Z":"c","RFC3339":"c","RFC3339Nano":"c","RFC822":"c","RFC822Z":"c","RFC850":"c","RubyDate":"c","Saturday":"c","Second":"c","September":"c","Since":"f","Sleep":"f","Stamp":"c","StampMicro":"c","StampMilli":"c","StampNano":"c","Sunday":"c","Thursday":"c","Tick":"f","Ticker":"t","Ticker.Reset":"m","Ticker.Stop":"m","Time":"t","Time.Add":"m","Time.AddDate":"m","Time.After":"m","Time.AppendBinary":"m","Time.AppendFormat":"m","Time.AppendText":"m","Time.Before":"m","Time.Clock":"m","Time.Compare":"m","Time.Date":"m","Time.Day":"m","Time.Equal":"m","Time.Format":"m","Time.GoString":"m","Time.GobDecode":"m","Time.GobEncode":"m","Time.Hour":"m","Time.ISOWeek":"m","Time.In":"m","Time.IsDST":"m","Time.IsZero":"m","Time.Local":"m","Time.Location":"m","Time.MarshalBinary":"m","Time.MarshalJSON":"m","Time.MarshalText":"m","Time.Minute":"m","Time.Month":"m","Time.Nanosecond":"m","Time.Round":"m","Time.Second":"m","Time.String":"m","Time.Sub":"m","Time.Truncate":"m","Time.UTC":"m","Time.Unix":"m","Time.UnixMicro":"m","Time.UnixMilli":"m","Time.UnixNano":"m","Time.UnmarshalBinary":"m","Time.UnmarshalJSON":"m","Time.UnmarshalText":"m","Time.Weekday":"m","Time.Year":"m","Time.YearDay":"m","Time.Zone":"m","Time.ZoneBounds":"m","TimeOnly":"c","Timer":"t","Timer.Reset":"m","Timer.Stop":"m","Tuesday":"c","UTC":"v","Unix":"f","UnixDate":"c","UnixMicro":"f","UnixMilli":"f","Until":"f","Wednesday":"c","Weekday":"t","Weekday.String":"m"}},"unicode":{"path":"unicode","name":"unicode","symbols":{"ASCII_Hex_Digit":"v","Adlam":"v","Ahom":"v","Anatolian_Hieroglyphs":"v","Arabic":"v","Armenian":"v","Avestan":"v","AzeriCase":"v","Balinese":"v","Bamum":"v","Bassa_Vah":"v","Batak":"v","Bengali":"v","Bhaiksuki":"v","Bidi_Control":"v","Bopomofo":"v","Brahmi":"v","Braille":"v","Buginese":"v","Buhid":"v","C":"v","Canadian_Aboriginal":"v","Carian":"v","CaseRange":"t","CaseRanges":"v","Categories":"v","CategoryAliases":"v","Caucasian_Albanian":"v","Cc":"v","Cf":"v","Chakma":"v","Cham":"v","Cherokee":"v","Chorasmian":"v","Cn":"v","Co":"v","Common":"v","Coptic":"v","Cs":"v","Cuneiform":"v","Cypriot":"v","Cypro_Minoan":"v","Cyrillic":"v","Dash":"v","Deprecated":"v","Deseret":"v","Devanagari":"v","Diacritic":"v","Digit":"v","Dives_Akuru":"v","Dogra":"v","Duployan":"v","Egyptian_Hieroglyphs":"v","Elbasan":"v","Elymaic":"v","Ethiopic":"v","Extender":"v","FoldCategory":"v","FoldScript":"v","Georgian":"v","Glagolitic":"v","Gothic":"v","Grantha":"v","GraphicRanges":"v","Greek":"v","Gujarati":"v","Gunjala_Gondi":"v","Gurmukhi":"v","Han":"v","Hangul":"v","Hanifi_Rohingya":"v","Hanunoo":"v","Hatran":"v","Hebrew":"v","Hex_Digit":"v","Hiragana":"v","Hyphen":"v","IDS_Binary_Operator":"v","IDS_Trinary_Operator":"v","Ideographic":"v","Imperial_Aramaic":"v","In":"f","Inherited":"v","Inscriptional_Pahlavi":"v","Inscriptional_Parthian":"v","Is":"f","IsControl":"f","IsDigit":"f","IsGraphic":"f","IsLetter":"f","IsLower":"f","IsMark":"f","IsNumber":"f","IsOneOf":"f","IsPrint":"f","IsPunct":"f","IsSpace":"f","IsSymbol":"f","IsTitle":"f","IsUpper":"f","Javanese":"v","Join_Control":"v","Kaithi":"v","Kannada":"v","Katakana":"v","Kawi":"v","Kayah_Li":"v","Kharoshthi":"v","Khitan_Small_Script":"v","Khmer":"v","Khojki":"v","Khudawadi":"v","L":"v","LC":"v","Lao":"v","Latin":"v","Lepcha":"v","Letter":"v","Limbu":"v","Linear_A":"v","Linear_B":"v","Lisu":"v","Ll":"v","Lm":"v","Lo":"v","Logical_Order_Exception":"v","Lower":"v","LowerCase":"c","Lt":"v","Lu":"v","Lycian":"v","Lydian":"v","M":"v","Mahajani":"v","Makasar":"v","Malayalam":"v","Mandaic":"v","Manichaean":"v","Marchen":"v","Mark":"v","Masaram_Gondi":"v","MaxASCII":"c","MaxCase":"c","MaxLatin1":"c","MaxRune":"c","Mc":"v","Me":"v","Medefaidrin":"v","Meetei_Mayek":"v","Mende_Kikakui":"v","Meroitic_Cursive":"v","Meroitic_Hieroglyphs":"v","Miao":"v","Mn":"v","Modi":"v","Mongolian":"v","Mro":"v","Multani":"v","Myanmar":"v","N":"v","Nabataean":"v","Nag_Mundari":"v","Nandinagari":"v","Nd":"v","New_Tai_Lue":"v","Newa":"v","Nko":"v","Nl":"v","No":"v","Noncharacter_Code_Point":"v","Number":"v","Nushu":"v","Nyiakeng_Puachue_Hmong":"v","Ogham":"v","Ol_Chiki":"v","Old_Hungarian":"v","Old_Italic":"v","Old_North_Arabian":"v","Old_Permic":"v","Old_Persian":"v","Old_Sogdian":"v","Old_South_Arabian":"v","Old_Turkic":"v","Old_Uyghur":"v","Oriya":"v","Osage":"v","Osmanya":"v","Other":"v","Other_Alphabetic":"v","Other_Default_Ignorable_Code_Point":"v","Other_Grapheme_Extend":"v","Other_ID_Continue":"v","Other_ID_Start":"v","Other_Lowercase":"v","Other_Math":"v","Other_Uppercase":"v","P":"v","Pahawh_Hmong":"v","Palmyrene":"v","Pattern_Syntax":"v","Pattern_White_Space":"v","Pau_Cin_Hau":"v","Pc":"v","Pd":"v","Pe":"v","Pf":"v","Phags_Pa":"v","Phoenician":"v","Pi":"v","Po":"v","Prepended_Concatenation_Mark":"v","PrintRanges":"v","Properties":"v","Ps":"v","Psalter_Pahlavi":"v","Punct":"v","Quotation_Mark":"v","Radical":"v","Range16":"t","Range32":"t","RangeTable":"t","Regional_Indicator":"v","Rejang":"v","ReplacementChar":"c","Runic":"v","S":"v","STerm":"v","Samaritan":"v","Saurashtra":"v","Sc":"v","Scripts":"v","Sentence_Terminal":"v","Sharada":"v","Shavian":"v","Siddham":"v","SignWriting":"v","SimpleFold":"f","Sinhala":"v","Sk":"v","Sm":"v","So":"v","Soft_Dotted":"v","Sogdian":"v","Sora_Sompeng":"v","Soyombo":"v","Space":"v","SpecialCase":"t","SpecialCase.ToLower":"m","SpecialCase.ToTitle":"m","SpecialCase.ToUpper":"m","Sundanese":"v","Syloti_Nagri":"v","Symbol":"v","Syriac":"v","Tagalog":"v","Tagbanwa":"v","Tai_Le":"v","Tai_Tham":"v","Tai_Viet":"v","Takri":"v","Tamil":"v","Tangsa":"v","Tangut":"v","Telugu":"v","Terminal_Punctuation":"v","Thaana":"v","Thai":"v","Tibetan":"v","Tifinagh":"v","Tirhuta":"v","Title":"v","TitleCase":"c","To":"f","ToLower":"f","ToTitle":"f","ToUpper":"f","Toto":"v","TurkishCase":"v","Ugaritic":"v","Unified_Ideograph":"v","Upper":"v","UpperCase":"c","UpperLower":"c","Vai":"v","Variation_Selector":"v","Version":"c","Vithkuqi":"v","Wancho":"v","Warang_Citi":"v","White_Space":"v","Yezidi":"v","Yi":"v","Z":"v","Zanabazar_Square":"v","Zl":"v","Zp":"v","Zs":"v"}},"unicode/utf16":{"path":"unicode/utf16","name":"utf16","symbols":{"AppendRune":"f","Decode":"f","DecodeRune":"f","Encode":"f","EncodeRune":"f","IsSurrogate":"f","RuneLen":"f"}},"unicode/utf8":{"path":"unicode/utf8","name":"utf8","symbols":{"AppendRune":"f","DecodeLastRune":"f","DecodeLastRuneInString":"f","DecodeRune":"f","DecodeRuneInString":"f","EncodeRune":"f","FullRune":"f","FullRuneInString":"f","MaxRune":"c","RuneCount":"f","RuneCountInString":"f","RuneError":"c","RuneLen":"f","RuneSelf":"c","RuneStart":"f","UTFMax":"c","Valid":"f","ValidRune":"f","ValidString":"f"}},"unique":{"path":"unique","name":"unique","symbols":{"Handle":"t","Make":"f"}},"unsafe":{"path":"unsafe","name":"unsafe","symbols":{"Add":"f","Alignof":"f","ArbitraryType":"t","IntegerType":"t","Offsetof":"f","Pointer":"t","Sizeof":"f","Slice":"f","SliceData":"f","String":"f","StringData":"f"}},"weak":{"path":"weak","name":"weak","symbols":{"Make":"f","Pointer":"t"}}} diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/stdlib_doclink.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/stdlib_doclink.go new file mode 100644 index 000000000..209a0c190 --- /dev/null +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/stdlib_doclink.go @@ -0,0 +1,319 @@ +// Package stdlib_doclink provides a checker for detecting potential doc links +// to standard library symbols. +package stdlib_doclink + +import ( + "fmt" + gdc "go/doc/comment" + "regexp" + "slices" + "strconv" + "strings" + + "github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/internal" + "github.com/godoc-lint/godoc-lint/pkg/model" + "github.com/godoc-lint/godoc-lint/pkg/util" +) + +// RequireStdlibDoclinkRule is the corresponding rule name. +const RequireStdlibDoclinkRule = model.RequireStdlibDoclinkRule + +var ruleSet = model.RuleSet{}.Add(RequireStdlibDoclinkRule) + +// StdlibDoclinkChecker checks for proper doc links to stdlib symbols. +type StdlibDoclinkChecker struct{} + +// NewStdlibDoclinkChecker returns a new instance of the corresponding checker. +func NewStdlibDoclinkChecker() *StdlibDoclinkChecker { + return &StdlibDoclinkChecker{} +} + +// GetCoveredRules implements the corresponding interface method. +func (r *StdlibDoclinkChecker) GetCoveredRules() model.RuleSet { + return ruleSet +} + +// Apply implements the corresponding interface method. +func (r *StdlibDoclinkChecker) Apply(actx *model.AnalysisContext) error { + includeTests := actx.Config.GetRuleOptions().RequireStdlibDoclinkIncludeTests + + docs := make(map[*model.CommentGroup]struct{}, 10*len(actx.InspectorResult.Files)) + + for _, ir := range util.AnalysisApplicableFiles(actx, includeTests, model.RuleSet{}.Add(RequireStdlibDoclinkRule)) { + if ir.PackageDoc != nil { + docs[ir.PackageDoc] = struct{}{} + } + + for _, sd := range ir.SymbolDecl { + if sd.ParentDoc != nil { + docs[sd.ParentDoc] = struct{}{} + } + if sd.Doc == nil { + continue + } + docs[sd.Doc] = struct{}{} + } + } + + if len(docs) == 0 { + return nil + } + + stdlib := stdlib() + pi := packageImports{ + importAsMap: make(map[string]string, 10), + badImportAs: make(map[string]struct{}, 10), + } + + for _, f := range actx.Pass.Files { + ft := util.GetPassFileToken(f, actx.Pass) + if ft == nil { + continue + } + + for _, imp := range f.Imports { + path, _ := strconv.Unquote(imp.Path.Value) + s, ok := stdlib[path] + if !ok { + // It's not a stdlib package. + continue + } + + var importedAs string + if imp.Name != nil { + alias := imp.Name.Name + if alias == "" || alias == "." || alias == "_" { + // We don't support _ or . imports. + continue + } + importedAs = alias + } else { + importedAs = s.Name + } + + if alreadyImportedPath, ok := pi.importAsMap[importedAs]; ok && alreadyImportedPath != path { + // Different import paths with the same alias(es); we don't support this case. + // It happens when people do aliasing like this: + // + // (foo.go) + // import blah "path/to/package" + // + // (bar.go) + // import blah "path/to/another/package" + // + // It's not inherently wrong, but due to the go doc tool's package-wide way of + // resolving package names in doc links (i.e. pkg in [pkg.name] or [pkg.recv.name]) + // it'll not work in such collision cases. As a result, doc links with colliding + // package aliases get rendered as plain text instead of links. + pi.badImportAs[importedAs] = struct{}{} + continue + } + + pi.importAsMap[importedAs] = path + } + } + + for doc := range docs { + checkStdlibDoclink(actx, &pi, doc) + } + return nil +} + +type packageImports struct { + importAsMap map[string]string + badImportAs map[string]struct{} +} + +func checkStdlibDoclink( + actx *model.AnalysisContext, + pi *packageImports, + doc *model.CommentGroup, +) { + if doc.DisabledRules.All || doc.DisabledRules.Rules.Has(RequireStdlibDoclinkRule) { + return + } + + applicableBlocks := make([]gdc.Block, 0, len(doc.Parsed.Content)) + for _, b := range doc.Parsed.Content { + if _, ok := b.(*gdc.Code); ok { + continue + } + // Doc links are not picked up in headings. + if _, ok := b.(*gdc.Heading); ok { + continue + } + applicableBlocks = append(applicableBlocks, b) + } + strippedCodeAndLinks := &gdc.Doc{ + Content: applicableBlocks, + } + text := string((&gdc.Printer{}).Comment(strippedCodeAndLinks)) + + pds := findPotentialDoclinks(pi, text) + if len(pds) == 0 { + return + } + + for _, pd := range pds { + var count string + if pd.count > 1 { + count = fmt.Sprintf(" (%d instances)", pd.count) + } + + actx.Pass.ReportRangef(&doc.CG, "text %q should be replaced with %q to link to stdlib %s%s", pd.originalNoStar, pd.doclink, kindTitle(pd.kind), count) + } +} + +func kindTitle(kind internal.SymbolKind) string { + switch kind { + case internal.SymbolKindType: + return "type" + case internal.SymbolKindFunc: + return "function" + case internal.SymbolKindVar: + return "variable" + case internal.SymbolKindConst: + return "constant" + case internal.SymbolKindMethod: + return "method" + default: + return "symbol" + } +} + +type potentialDoclink struct { + originalNoStar string // e.g. "encoding/json.Encoder" or "json.Encoder" (if imported as such) + count int + doclink string + kind internal.SymbolKind +} + +var potentialDoclinkRE = regexp.MustCompile(`(?m)(?:^|\s)(\*?)([a-zA-Z_][a-zA-Z0-9_]*(?:/[a-zA-Z_][a-zA-Z0-9_]*)*)\.([a-zA-Z0-9_]+)(?:\.([a-zA-Z0-9_]+))?\b`) + +func findPotentialDoclinks(pi *packageImports, text string) []potentialDoclink { + stdlib := stdlib() + + m := make(map[string]*potentialDoclink, 5) + + matches := potentialDoclinkRE.FindAllStringSubmatch(text, -1) + for _, match := range matches { + _ = match[1] // star, if any + pkg := match[2] + name1 := match[3] + name2 := match[4] + + if pkg != "" && name1 != "" && name2 != "" { + // pkg.recv.name (= pkg.name1.name2) + + path := pi.tryResolveImportPath(pkg) + if path == "" { + // Colliding import alias/name; skip. + continue + } + + s, ok := stdlib[path] + if !ok { + continue + } + + kind, ok := s.Symbols[name1+"."+name2] + if !ok { + continue + } + + originalNoStar := fmt.Sprintf("%s.%s.%s", pkg, name1, name2) + if _, ok := m[originalNoStar]; !ok { + doclink := fmt.Sprintf("[%s]", originalNoStar) + m[originalNoStar] = &potentialDoclink{ + originalNoStar: originalNoStar, + doclink: doclink, + kind: kind, + } + } + m[originalNoStar].count = m[originalNoStar].count + 1 + } else if pkg != "" && name1 != "" && name2 == "" { + // pkg.name (= pkg.name1) + + path := pi.tryResolveImportPath(pkg) + if path == "" { + // Colliding import alias/name; skip. + continue + } + + s, ok := stdlib[path] + if !ok { + continue + } + + kind, ok := s.Symbols[name1] + if !ok { + continue + } + + originalNoStar := fmt.Sprintf("%s.%s", pkg, name1) + if _, ok := m[originalNoStar]; !ok { + doclink := fmt.Sprintf("[%s]", originalNoStar) + m[originalNoStar] = &potentialDoclink{ + originalNoStar: originalNoStar, + doclink: doclink, + kind: kind, + } + } + m[originalNoStar].count = m[originalNoStar].count + 1 + } + } + + if len(m) == 0 { + return nil + } + + result := make([]potentialDoclink, 0, len(m)) + for _, v := range m { + result = append(result, *v) + } + slices.SortFunc(result, func(a, b potentialDoclink) int { + return strings.Compare(a.originalNoStar, b.originalNoStar) + }) + return result +} + +// tryResolveImportPath tries to resolve the given package alias/name to its +// import path (package-wide lookup of imports). If the alias/name was among the +// existing imports, the method will return the underlying import path; +// otherwise it'll return the given argument as is. +// +// If the package alias/name is among bad/colliding imports, an empty string is +// returned. +// +// When spotting potential doc links like "pkg.name" or "pkg.recv.name", we +// should resolve the "pkg" part to the underlying import path. Not only that +// users can have a totally new/unknown alias for a stdlib package import, like: +// +// import blah "encoding/json" +// +// they can also use another stdlib package's name as the alias, like: +// +// import fmt "encoding/json" +// +// This is obviously rare, but still a valid use of language. +// +// Additionally, when importing slashed package paths, like "encoding/json", +// the package will be available as "json" by default; i.e.: +// +// import "encoding/json" +// +// So, the actual package is not always evident from the import alias/name, so +// we need to carefully resolve the "pkg" part. +func (pi *packageImports) tryResolveImportPath(pkg string) string { + path, ok := pi.importAsMap[pkg] + if ok { + if _, isBad := pi.badImportAs[pkg]; isBad { + // We have different import paths with the same alias. + return "" + } + return path + } + + // Given "pkg" is not among existing imports. + return pkg +} diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/builder.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/builder.go index aa25cf186..7000669da 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/builder.go +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/builder.go @@ -260,6 +260,20 @@ func (cb *ConfigBuilder) build(cwd string) (*config, error) { } } + var maxLenIgnore []*regexp.Regexp + rawMaxLenIgnore := def.Options.MaxLenIgnorePatterns + if pcfg.Options != nil && pcfg.Options.MaxLenIgnorePatterns != nil { + rawMaxLenIgnore = pcfg.Options.MaxLenIgnorePatterns + } + if len(rawMaxLenIgnore) > 0 { + rs, invalids := toValidRegexpSlice(rawMaxLenIgnore) + if len(invalids) > 0 { + errs = append(errs, fmt.Errorf("invalid max-len ignore pattern(s): %q", invalids)) + } else { + maxLenIgnore = rs + } + } + if errs != nil { return nil, errors.Join(errs...) } @@ -274,10 +288,12 @@ func (cb *ConfigBuilder) build(cwd string) (*config, error) { // To avoid being too strict, we don't complain if a rule is enabled and disabled at the same time. resolvedOptions := &model.RuleOptions{} - transferOptions(resolvedOptions, def.Options) // def.Options is never nil + transferPrimitiveOptions(resolvedOptions, def.Options) // def.Options is never nil if pcfg.Options != nil { - transferOptions(resolvedOptions, pcfg.Options) + transferPrimitiveOptions(resolvedOptions, pcfg.Options) } + resolvedOptions.MaxLenIgnorePatterns = maxLenIgnore + result.options = resolvedOptions return result, nil @@ -287,3 +303,25 @@ func (cb *ConfigBuilder) build(cwd string) (*config, error) { func (cb *ConfigBuilder) SetOverride(override *model.ConfigOverride) { cb.override = override } + +func transferPrimitiveOptions(target *model.RuleOptions, source *PlainRuleOptions) { + transferIfNotNil(&target.MaxLenLength, source.MaxLenLength) + transferIfNotNil(&target.MaxLenIncludeTests, source.MaxLenIncludeTests) + transferIfNotNil(&target.PkgDocIncludeTests, source.PkgDocIncludeTests) + transferIfNotNil(&target.SinglePkgDocIncludeTests, source.SinglePkgDocIncludeTests) + transferIfNotNil(&target.RequirePkgDocIncludeTests, source.RequirePkgDocIncludeTests) + transferIfNotNil(&target.RequireDocIncludeTests, source.RequireDocIncludeTests) + transferIfNotNil(&target.RequireDocIgnoreExported, source.RequireDocIgnoreExported) + transferIfNotNil(&target.RequireDocIgnoreUnexported, source.RequireDocIgnoreUnexported) + transferIfNotNil(&target.StartWithNameIncludeTests, source.StartWithNameIncludeTests) + transferIfNotNil(&target.StartWithNameIncludeUnexported, source.StartWithNameIncludeUnexported) + transferIfNotNil(&target.RequireStdlibDoclinkIncludeTests, source.RequireStdlibDoclinkIncludeTests) + transferIfNotNil(&target.NoUnusedLinkIncludeTests, source.NoUnusedLinkIncludeTests) +} + +func transferIfNotNil[T any](dst *T, src *T) { + if src == nil { + return + } + *dst = *src +} diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/default.yaml b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/default.yaml index eb244e771..967897836 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/default.yaml +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/default.yaml @@ -4,6 +4,7 @@ default: basic options: max-len/length: 77 max-len/include-tests: false + max-len/ignore-patterns: [] pkg-doc/include-tests: false single-pkg-doc/include-tests: false require-pkg-doc/include-tests: false @@ -12,4 +13,5 @@ options: require-doc/ignore-unexported: true start-with-name/include-tests: false start-with-name/include-unexported: false + require-stdlib-doclink/include-tests: false no-unused-link/include-tests: false \ No newline at end of file diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/parser.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/parser.go index 71a04f045..3db9398c2 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/parser.go +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/parser.go @@ -5,7 +5,7 @@ import ( "os" "strings" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" ) // FromYAML parses configuration from given YAML content. diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/plain.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/plain.go index d19323f3f..0ff094855 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/plain.go +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/config/plain.go @@ -3,7 +3,6 @@ package config import ( "errors" "fmt" - "reflect" "regexp" "slices" @@ -25,54 +24,19 @@ type PlainConfig struct { // PlainRuleOptions represents the plain rule options as users would provide via // a config file (e.g., a YAML file). type PlainRuleOptions struct { - MaxLenLength *uint `option:"max-len/length" yaml:"max-len/length" mapstructure:"max-len/length"` - MaxLenIncludeTests *bool `option:"max-len/include-tests" yaml:"max-len/include-tests" mapstructure:"max-len/include-tests"` - PkgDocIncludeTests *bool `option:"pkg-doc/include-tests" yaml:"pkg-doc/include-tests" mapstructure:"pkg-doc/include-tests"` - SinglePkgDocIncludeTests *bool `option:"single-pkg-doc/include-tests" yaml:"single-pkg-doc/include-tests" mapstructure:"single-pkg-doc/include-tests"` - RequirePkgDocIncludeTests *bool `option:"require-pkg-doc/include-tests" yaml:"require-pkg-doc/include-tests" mapstructure:"require-pkg-doc/include-tests"` - RequireDocIncludeTests *bool `option:"require-doc/include-tests" yaml:"require-doc/include-tests" mapstructure:"require-doc/include-tests"` - RequireDocIgnoreExported *bool `option:"require-doc/ignore-exported" yaml:"require-doc/ignore-exported" mapstructure:"require-doc/ignore-exported"` - RequireDocIgnoreUnexported *bool `option:"require-doc/ignore-unexported" yaml:"require-doc/ignore-unexported" mapstructure:"require-doc/ignore-unexported"` - StartWithNameIncludeTests *bool `option:"start-with-name/include-tests" yaml:"start-with-name/include-tests" mapstructure:"start-with-name/include-tests"` - StartWithNameIncludeUnexported *bool `option:"start-with-name/include-unexported" yaml:"start-with-name/include-unexported" mapstructure:"start-with-name/include-unexported"` - NoUnusedLinkIncludeTests *bool `option:"no-unused-link/include-tests" yaml:"no-unused-link/include-tests" mapstructure:"no-unused-link/include-tests"` -} - -func transferOptions(target *model.RuleOptions, source *PlainRuleOptions) { - resV := reflect.ValueOf(target).Elem() - resVT := resV.Type() - - resOptionMap := make(map[string]string, resVT.NumField()) - for i := range resVT.NumField() { - ft := resVT.Field(i) - key, ok := ft.Tag.Lookup("option") - if !ok { - continue - } - resOptionMap[key] = ft.Name - } - - v := reflect.ValueOf(source).Elem() - vt := v.Type() - for i := range vt.NumField() { - ft := vt.Field(i) - key, ok := ft.Tag.Lookup("option") - if !ok { - continue - } - if ft.Type.Kind() != reflect.Pointer { - continue - } - f := v.Field(i) - if f.IsNil() { - continue - } - resFieldName, ok := resOptionMap[key] - if !ok { - continue - } - resV.FieldByName(resFieldName).Set(f.Elem()) - } + MaxLenLength *uint `yaml:"max-len/length" mapstructure:"max-len/length"` + MaxLenIncludeTests *bool `yaml:"max-len/include-tests" mapstructure:"max-len/include-tests"` + MaxLenIgnorePatterns []string `yaml:"max-len/ignore-patterns" mapstructure:"max-len/ignore-patterns"` + PkgDocIncludeTests *bool `yaml:"pkg-doc/include-tests" mapstructure:"pkg-doc/include-tests"` + SinglePkgDocIncludeTests *bool `yaml:"single-pkg-doc/include-tests" mapstructure:"single-pkg-doc/include-tests"` + RequirePkgDocIncludeTests *bool `yaml:"require-pkg-doc/include-tests" mapstructure:"require-pkg-doc/include-tests"` + RequireDocIncludeTests *bool `yaml:"require-doc/include-tests" mapstructure:"require-doc/include-tests"` + RequireDocIgnoreExported *bool `yaml:"require-doc/ignore-exported" mapstructure:"require-doc/ignore-exported"` + RequireDocIgnoreUnexported *bool `yaml:"require-doc/ignore-unexported" mapstructure:"require-doc/ignore-unexported"` + StartWithNameIncludeTests *bool `yaml:"start-with-name/include-tests" mapstructure:"start-with-name/include-tests"` + StartWithNameIncludeUnexported *bool `yaml:"start-with-name/include-unexported" mapstructure:"start-with-name/include-unexported"` + RequireStdlibDoclinkIncludeTests *bool `yaml:"require-stdlib-doclink/include-tests" mapstructure:"require-stdlib-doclink/include-tests"` + NoUnusedLinkIncludeTests *bool `yaml:"no-unused-link/include-tests" mapstructure:"no-unused-link/include-tests"` } // Validate validates the plain configuration. @@ -101,6 +65,12 @@ func (pcfg *PlainConfig) Validate() error { errs = append(errs, fmt.Errorf("invalid exclusion pattern(s): %q", invalids)) } + if pcfg.Options != nil { + if invalids := getInvalidRegexps(pcfg.Options.MaxLenIgnorePatterns); len(invalids) > 0 { + errs = append(errs, fmt.Errorf("invalid max-len ignore pattern(s): %q", invalids)) + } + } + if len(errs) > 0 { return errors.Join(errs...) } diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/inspect/inspector.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/inspect/inspector.go index 0040be0e0..11e41c426 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/inspect/inspector.go +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/inspect/inspector.go @@ -42,7 +42,7 @@ func NewInspector(cb model.ConfigBuilder, exitFunc func(int, error)) *Inspector Name: metaName, Doc: metaDoc, URL: metaURL, - ResultType: reflect.TypeOf(new(model.InspectorResult)), + ResultType: reflect.TypeFor[*model.InspectorResult](), }, } result.analyzer.Run = result.run @@ -107,12 +107,24 @@ func (i *Inspector) run(pass *analysis.Pass) (any, error) { for _, d := range f.Decls { switch dt := d.(type) { case *ast.FuncDecl: + var recvBaseTypeName string + var isMethod bool + + if dt.Recv != nil { + isMethod = true + if len(dt.Recv.List) > 0 { + recvBaseTypeName = extractMethodRecvBaseTypeName(dt.Recv.List[0].Type) + } + } + decls = append(decls, model.SymbolDecl{ - Decl: d, - Kind: model.SymbolDeclKindFunc, - Name: dt.Name.Name, - Ident: dt.Name, - Doc: i.extractCommentGroup(dt.Doc), + Decl: d, + Kind: model.SymbolDeclKindFunc, + Name: dt.Name.Name, + Ident: dt.Name, + IsMethod: isMethod, + MethodRecvBaseTypeName: recvBaseTypeName, + Doc: i.extractCommentGroup(dt.Doc), }) case *ast.BadDecl: decls = append(decls, model.SymbolDecl{ @@ -310,3 +322,17 @@ func extractDisableDirectivesInComment(s string) model.InspectorResultDisableRul } return result } + +func extractMethodRecvBaseTypeName(expr ast.Expr) string { + switch tt := expr.(type) { + case *ast.Ident: + return tt.Name + case *ast.StarExpr: + return extractMethodRecvBaseTypeName(tt.X) + case *ast.IndexExpr: + return extractMethodRecvBaseTypeName(tt.X) + case *ast.IndexListExpr: + return extractMethodRecvBaseTypeName(tt.X) + } + return "" +} diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/config.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/config.go index 78fa62a27..5ba271a3c 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/config.go +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/config.go @@ -109,15 +109,17 @@ type Config interface { // RuleOptions represents individual linter rule configurations. type RuleOptions struct { - MaxLenLength uint `option:"max-len/length"` - MaxLenIncludeTests bool `option:"max-len/include-tests"` - PkgDocIncludeTests bool `option:"pkg-doc/include-tests"` - SinglePkgDocIncludeTests bool `option:"single-pkg-doc/include-tests"` - RequirePkgDocIncludeTests bool `option:"require-pkg-doc/include-tests"` - RequireDocIncludeTests bool `option:"require-doc/include-tests"` - RequireDocIgnoreExported bool `option:"require-doc/ignore-exported"` - RequireDocIgnoreUnexported bool `option:"require-doc/ignore-unexported"` - StartWithNameIncludeTests bool `option:"start-with-name/include-tests"` - StartWithNameIncludeUnexported bool `option:"start-with-name/include-unexported"` - NoUnusedLinkIncludeTests bool `option:"no-unused-link/include-tests"` + MaxLenLength uint + MaxLenIncludeTests bool + MaxLenIgnorePatterns []*regexp.Regexp + PkgDocIncludeTests bool + SinglePkgDocIncludeTests bool + RequirePkgDocIncludeTests bool + RequireDocIncludeTests bool + RequireDocIgnoreExported bool + RequireDocIgnoreUnexported bool + StartWithNameIncludeTests bool + StartWithNameIncludeUnexported bool + RequireStdlibDoclinkIncludeTests bool + NoUnusedLinkIncludeTests bool } diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/inspector.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/inspector.go index 3166e17fa..9b4846634 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/inspector.go +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/inspector.go @@ -71,12 +71,40 @@ type SymbolDecl struct { // This is always false for non-type declaration (e.g., const or var). IsTypeAlias bool + // IsMethod indicates whether the symbol is a method. For example: + // + // func (Foo) Bar() {} + // func (*Foo) Bar() {} + // func (Foo[T]) Bar() {} + // func (*Foo[T]) Bar() {} + // + // This field is false for non-function declarations. + IsMethod bool + // Name is the name of the declared symbol. Name string // Ident is the symbol identifier node. Ident *ast.Ident + // MethodRecvBaseTypeName is the base type name of the method receiver, if + // the symbol is a method (See [Go spec]). + // + // Note that although an empty value is unexpected for method declarations, + // it's still possible (e.g. due to new language features that we don't yet + // support). So, users of this field should always check for empty values. + // + // In the examples below the base type name is "Foo": + // + // func (Foo) Bar() {} + // func (*Foo) Bar() {} + // func (Foo[T]) BarFoo() {} + // + // This field is empty for non-method symbols. + // + // [Go spec]: https://go.dev/ref/spec#Method_declarations + MethodRecvBaseTypeName string + // MultiNameDecl determines whether the symbol is declared as part of a // multi-name declaration spec; For example: // @@ -172,7 +200,7 @@ type SymbolDecl struct { ParentDoc *CommentGroup } -// CommentGroup represents an ast.CommentGroup and its parsed godoc instance. +// CommentGroup represents an [ast.CommentGroup] and its parsed godoc instance. type CommentGroup struct { // CG represents the AST comment group. CG ast.CommentGroup diff --git a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/rule.go b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/rule.go index c53fcf61a..eb7a67ff4 100644 --- a/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/rule.go +++ b/tools/vendor/github.com/godoc-lint/godoc-lint/pkg/model/rule.go @@ -16,6 +16,8 @@ const ( RequireDocRule Rule = "require-doc" // DeprecatedRule represents the "deprecated" rule. DeprecatedRule Rule = "deprecated" + // RequireStdlibDoclinkRule represents the "require-stdlib-doclink" rule. + RequireStdlibDoclinkRule Rule = "require-stdlib-doclink" // MaxLenRule represents the "max-len" rule. MaxLenRule Rule = "max-len" // NoUnusedLinkRule represents the "no-unused-link" rule. @@ -31,6 +33,7 @@ var AllRules = func() RuleSet { StartWithNameRule, RequireDocRule, DeprecatedRule, + RequireStdlibDoclinkRule, MaxLenRule, NoUnusedLinkRule, ) diff --git a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go index fefa94ca3..6c8554d99 100644 --- a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go +++ b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/config/linters_settings.go @@ -164,7 +164,22 @@ var defaultLintersSettings = LintersSettings{ AllowPackages: []string{"main"}, }, Unqueryvet: UnqueryvetSettings{ - CheckSQLBuilders: true, + CheckSQLBuilders: true, + CheckAliasedWildcard: true, + CheckStringConcat: true, + CheckFormatStrings: true, + CheckStringBuilder: true, + CheckSubqueries: true, + SQLBuilders: UnqueryvetSQLBuildersSettings{ + Squirrel: true, + GORM: true, + SQLx: true, + Ent: true, + PGX: true, + Bun: true, + SQLBoiler: true, + Jet: true, + }, }, Unused: UnusedSettings{ FieldWritesAreUses: true, @@ -575,6 +590,7 @@ type GoModDirectivesSettings struct { ToolForbidden bool `mapstructure:"tool-forbidden"` GoDebugForbidden bool `mapstructure:"go-debug-forbidden"` GoVersionPattern string `mapstructure:"go-version-pattern"` + CheckModulePath bool `mapstructure:"check-module-path"` } type GoModGuardSettings struct { @@ -1021,8 +1037,26 @@ type UnparamSettings struct { } type UnqueryvetSettings struct { - CheckSQLBuilders bool `mapstructure:"check-sql-builders"` - AllowedPatterns []string `mapstructure:"allowed-patterns"` + CheckSQLBuilders bool `mapstructure:"check-sql-builders"` + AllowedPatterns []string `mapstructure:"allowed-patterns"` + IgnoredFunctions []string `mapstructure:"ignored-functions"` + CheckAliasedWildcard bool `mapstructure:"check-aliased-wildcard"` + CheckStringConcat bool `mapstructure:"check-string-concat"` + CheckFormatStrings bool `mapstructure:"check-format-strings"` + CheckStringBuilder bool `mapstructure:"check-string-builder"` + CheckSubqueries bool `mapstructure:"check-subqueries"` + SQLBuilders UnqueryvetSQLBuildersSettings `mapstructure:"sql-builders"` +} + +type UnqueryvetSQLBuildersSettings struct { + Squirrel bool `mapstructure:"squirrel"` + GORM bool `mapstructure:"gorm"` + SQLx bool `mapstructure:"sqlx"` + Ent bool `mapstructure:"ent"` + PGX bool `mapstructure:"pgx"` + Bun bool `mapstructure:"bun"` + SQLBoiler bool `mapstructure:"sqlboiler"` + Jet bool `mapstructure:"jet"` } type UnusedSettings struct { diff --git a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/golines/golines.go b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/golines/golines.go index ffd5b5f81..7c054866d 100644 --- a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/golines/golines.go +++ b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/goformatters/golines/golines.go @@ -1,7 +1,7 @@ package golines import ( - "github.com/golangci/golines" + "github.com/golangci/golines/shorten" "github.com/golangci/golangci-lint/v2/pkg/config" ) @@ -9,27 +9,25 @@ import ( const Name = "golines" type Formatter struct { - shortener *golines.Shortener + shortener *shorten.Shortener } func New(settings *config.GoLinesSettings) *Formatter { - options := golines.ShortenerConfig{} + cfg := &shorten.Config{} if settings != nil { - options = golines.ShortenerConfig{ - MaxLen: settings.MaxLen, - TabLen: settings.TabLen, - KeepAnnotations: false, // golines debug (not usable inside golangci-lint) - ShortenComments: settings.ShortenComments, - ReformatTags: settings.ReformatTags, - IgnoreGenerated: false, // handle globally - DotFile: "", // golines debug (not usable inside golangci-lint) - ChainSplitDots: settings.ChainSplitDots, - BaseFormatterCmd: "go fmt", // fake cmd + cfg = &shorten.Config{ + MaxLen: settings.MaxLen, + TabLen: settings.TabLen, + KeepAnnotations: false, // golines debug (not usable inside golangci-lint) + ShortenComments: settings.ShortenComments, + ReformatTags: settings.ReformatTags, + DotFile: "", // golines debug (not usable inside golangci-lint) + ChainSplitDots: settings.ChainSplitDots, } } - return &Formatter{shortener: golines.NewShortener(options)} + return &Formatter{shortener: shorten.NewShortener(cfg)} } func (*Formatter) Name() string { @@ -37,5 +35,5 @@ func (*Formatter) Name() string { } func (f *Formatter) Format(_ string, src []byte) ([]byte, error) { - return f.shortener.Shorten(src) + return f.shortener.Process(src) } diff --git a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errorlint/errorlint.go b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errorlint/errorlint.go index f32217796..a92cb4c18 100644 --- a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errorlint/errorlint.go +++ b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/errorlint/errorlint.go @@ -1,7 +1,7 @@ package errorlint import ( - "github.com/polyfloyd/go-errorlint/errorlint" + "codeberg.org/polyfloyd/go-errorlint/errorlint" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" diff --git a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint/godoclint.go b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint/godoclint.go index 235909217..0d0171251 100644 --- a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint/godoclint.go +++ b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/godoclint/godoclint.go @@ -35,25 +35,35 @@ func New(settings *config.GodoclintSettings) *goanalysis.Linter { // - Options.RequireDocIncludeTests // - Options.StartWithNameIncludeTests // - Options.NoUnusedLinkIncludeTests + // - Options.RequireStdlibDoclinkIncludeTests + + // Also, Options.MaxLenIgnorePatterns is ignored because the Golangci-lint's idiomatic way to ignore such issues + // is exclusion by source text patterns. pcfg = glconfig.PlainConfig{ Default: settings.Default, Enable: settings.Enable, Disable: settings.Disable, Options: &glconfig.PlainRuleOptions{ - MaxLenLength: settings.Options.MaxLen.Length, - MaxLenIncludeTests: pointer(true), - PkgDocIncludeTests: pointer(false), - SinglePkgDocIncludeTests: pointer(true), - RequirePkgDocIncludeTests: pointer(false), - RequireDocIncludeTests: pointer(true), - RequireDocIgnoreExported: settings.Options.RequireDoc.IgnoreExported, - RequireDocIgnoreUnexported: settings.Options.RequireDoc.IgnoreUnexported, - StartWithNameIncludeTests: pointer(false), - StartWithNameIncludeUnexported: settings.Options.StartWithName.IncludeUnexported, - NoUnusedLinkIncludeTests: pointer(true), + MaxLenLength: settings.Options.MaxLen.Length, + MaxLenIncludeTests: pointer(true), + MaxLenIgnorePatterns: []string{`^\+kubebuilder:`}, + PkgDocIncludeTests: pointer(false), + SinglePkgDocIncludeTests: pointer(true), + RequirePkgDocIncludeTests: pointer(false), + RequireDocIncludeTests: pointer(true), + RequireDocIgnoreExported: settings.Options.RequireDoc.IgnoreExported, + RequireDocIgnoreUnexported: settings.Options.RequireDoc.IgnoreUnexported, + StartWithNameIncludeTests: pointer(false), + StartWithNameIncludeUnexported: settings.Options.StartWithName.IncludeUnexported, + RequireStdlibDoclinkIncludeTests: pointer(true), + NoUnusedLinkIncludeTests: pointer(true), }, } + + if err := pcfg.Validate(); err != nil { + internal.LinterLogger.Fatalf("godoclint: %v", err) + } } composition := glcompose.Compose(glcompose.CompositionConfig{ diff --git a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go index dd6656fb6..817b5498e 100644 --- a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go +++ b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives/gomoddirectives.go @@ -29,6 +29,7 @@ func New(settings *config.GoModDirectivesSettings) *goanalysis.Linter { opts.ToolchainForbidden = settings.ToolchainForbidden opts.ToolForbidden = settings.ToolForbidden opts.GoDebugForbidden = settings.GoDebugForbidden + opts.CheckModulePath = settings.CheckModulePath if settings.ToolchainPattern != "" { exp, err := regexp.Compile(settings.ToolchainPattern) diff --git a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/modernize/modernize.go b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/modernize/modernize.go index 08cccdeb8..97825c07e 100644 --- a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/modernize/modernize.go +++ b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/modernize/modernize.go @@ -14,9 +14,9 @@ func New(settings *config.ModernizeSettings) *goanalysis.Linter { var analyzers []*analysis.Analyzer if settings == nil { - analyzers = cleanSuite() + analyzers = modernize.Suite } else { - for _, analyzer := range cleanSuite() { + for _, analyzer := range modernize.Suite { if slices.Contains(settings.Disable, analyzer.Name) { continue } @@ -32,19 +32,3 @@ func New(settings *config.ModernizeSettings) *goanalysis.Linter { nil). WithLoadMode(goanalysis.LoadModeTypesInfo) } - -func cleanSuite() []*analysis.Analyzer { - var analyzers []*analysis.Analyzer - - for _, analyzer := range modernize.Suite { - // Disabled because of false positives - // https://github.com/golang/go/issues/76687 - if analyzer.Name == "stringscut" { - continue - } - - analyzers = append(analyzers, analyzer) - } - - return analyzers -} diff --git a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/prealloc/prealloc.go b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/prealloc/prealloc.go index c750df990..3dbe3822a 100644 --- a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/prealloc/prealloc.go +++ b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/prealloc/prealloc.go @@ -1,14 +1,11 @@ package prealloc import ( - "fmt" - "github.com/alexkohler/prealloc/pkg" "golang.org/x/tools/go/analysis" "github.com/golangci/golangci-lint/v2/pkg/config" "github.com/golangci/golangci-lint/v2/pkg/goanalysis" - "github.com/golangci/golangci-lint/v2/pkg/golinters/internal" ) func New(settings *config.PreallocSettings) *goanalysis.Linter { @@ -29,9 +26,6 @@ func runPreAlloc(pass *analysis.Pass, settings *config.PreallocSettings) { hints := pkg.Check(pass.Files, settings.Simple, settings.RangeLoops, settings.ForLoops) for _, hint := range hints { - pass.Report(analysis.Diagnostic{ - Pos: hint.Pos, - Message: fmt.Sprintf("Consider pre-allocating %s", internal.FormatCode(hint.DeclaredSliceName)), - }) + pass.Report(hint) } } diff --git a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go index 6799e1a42..63d710d32 100644 --- a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go +++ b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/revive/revive.go @@ -155,9 +155,11 @@ func (w *wrapper) toIssue(pass *analysis.Pass, failure *lint.Failure) *goanalysi if failure.Filename() == f.Name() { issue.SuggestedFixes = []analysis.SuggestedFix{{ TextEdits: []analysis.TextEdit{{ - Pos: f.LineStart(failure.Position.Start.Line), - End: goanalysis.EndOfLinePos(f, failure.Position.End.Line), - NewText: []byte(failure.ReplacementLine), + Pos: f.LineStart(failure.Position.Start.Line), + End: goanalysis.EndOfLinePos(f, failure.Position.End.Line), + // ReplacementLine doesn't contain the full line (missing newline), so we have to add a newline. + // Also `failure.Position.End.Offset` is at the end of the node but not the line. + NewText: []byte(failure.ReplacementLine + "\n"), }}, }} } @@ -208,11 +210,12 @@ func getConfig(cfg *config.ReviveSettings) (*lint.Config, error) { func createConfigMap(cfg *config.ReviveSettings) map[string]any { rawRoot := map[string]any{ - "confidence": cfg.Confidence, - "severity": cfg.Severity, - "errorCode": cfg.ErrorCode, - "warningCode": cfg.WarningCode, - "enableAllRules": cfg.EnableAllRules, + "confidence": cfg.Confidence, + "severity": cfg.Severity, + "errorCode": cfg.ErrorCode, + "warningCode": cfg.WarningCode, + "enableAllRules": cfg.EnableAllRules, + "enableDefaultRules": cfg.EnableDefaultRules, // Should be managed with `linters.exclusions.generated`. "ignoreGeneratedHeader": false, diff --git a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unqueryvet/unqueryvet.go b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unqueryvet/unqueryvet.go index db4a4d752..c6aad8860 100644 --- a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unqueryvet/unqueryvet.go +++ b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/golinters/unqueryvet/unqueryvet.go @@ -12,10 +12,29 @@ func New(settings *config.UnqueryvetSettings) *goanalysis.Linter { cfg := pkgconfig.DefaultSettings() if settings != nil { + // IgnoredFiles, and Severity are explicitly ignored. cfg.CheckSQLBuilders = settings.CheckSQLBuilders + cfg.CheckAliasedWildcard = settings.CheckAliasedWildcard + cfg.CheckStringConcat = settings.CheckStringConcat + cfg.CheckFormatStrings = settings.CheckFormatStrings + cfg.CheckStringBuilder = settings.CheckStringBuilder + cfg.CheckSubqueries = settings.CheckSubqueries + cfg.IgnoredFunctions = settings.IgnoredFunctions + if len(settings.AllowedPatterns) > 0 { cfg.AllowedPatterns = settings.AllowedPatterns } + + cfg.SQLBuilders = pkgconfig.SQLBuildersConfig{ + Squirrel: settings.SQLBuilders.Squirrel, + GORM: settings.SQLBuilders.GORM, + SQLx: settings.SQLBuilders.SQLx, + Ent: settings.SQLBuilders.Ent, + PGX: settings.SQLBuilders.PGX, + Bun: settings.SQLBuilders.Bun, + SQLBoiler: settings.SQLBuilders.SQLBoiler, + Jet: settings.SQLBuilders.Jet, + } } return goanalysis. diff --git a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go index 6e9cef1d1..b1abb6db9 100644 --- a/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go +++ b/tools/vendor/github.com/golangci/golangci-lint/v2/pkg/lint/lintersdb/builder_linter.go @@ -242,7 +242,7 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) { WithSince("v1.32.0"). WithLoadForGoAnalysis(). WithAutoFix(). - WithURL("https://github.com/polyfloyd/go-errorlint"), + WithURL("https://codeberg.org/polyfloyd/go-errorlint"), linter.NewConfig(exhaustive.New(&cfg.Linters.Settings.Exhaustive)). WithSince("v1.28.0"). diff --git a/tools/vendor/github.com/golangci/golines/.gitattributes b/tools/vendor/github.com/golangci/golines/.gitattributes deleted file mode 100644 index 148ff868c..000000000 --- a/tools/vendor/github.com/golangci/golines/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -_fixtures/* text eol=lf diff --git a/tools/vendor/github.com/golangci/golines/.gitignore b/tools/vendor/github.com/golangci/golines/.gitignore deleted file mode 100644 index 48e5593d2..000000000 --- a/tools/vendor/github.com/golangci/golines/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib -/dist - -# Test binary, build with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -vendor -.vscode -.idea -golines - -coverage.out diff --git a/tools/vendor/github.com/golangci/golines/README.md b/tools/vendor/github.com/golangci/golines/README.md deleted file mode 100644 index 24ec221a0..000000000 --- a/tools/vendor/github.com/golangci/golines/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Fork of golines - -This is a fork of [golines](https://github.com/segmentio/golines) to be usable as a library. - -## Modifications - -- The original code is under the `main` package -> uses `golines` package. -- Some files have been removed to reduce dependencies: - - `main.go`, `main_test.go` - - `graph.go`, `graph_generated.go`, `graph.test` - - `diff.go`, `diff_test.go` - - `doc.go` -- Some other files have been removed because unused by the fork: - - `.goreleaser.yaml`, `.pre-commit-hooks.yaml` - - `.github/build.yml`, `.github/release.yml` - - `Makefile` -- The workflow files (`lint.yml` and `test.yml`) are modified to run for this fork. -- The file `shortener.go` has been modified: - - The `baseFormatterCmd` is hardcoded. - - The code related to debug logs has been removed. - - The code related to graph has been removed. -- The module name has been changed to `github.com/golangci/golines` to avoid replacement directives inside golangci-lint. - -**No modifications will be accepted other than the synchronization of the fork.** - -The synchronization of the fork will be done by the golangci-lint maintainers only. - -## History - -- sync with fc305205784a70b4cfc17397654f4c94e3153ce4 (after v0.12.2) diff --git a/tools/vendor/github.com/golangci/golines/annotation.go b/tools/vendor/github.com/golangci/golines/annotation.go deleted file mode 100644 index fc7f92ca2..000000000 --- a/tools/vendor/github.com/golangci/golines/annotation.go +++ /dev/null @@ -1,99 +0,0 @@ -package golines - -import ( - "fmt" - "strconv" - "strings" - - "github.com/dave/dst" -) - -const annotationPrefix = "// __golines:shorten:" - -// CreateAnnotation generates the text of a comment that will annotate long lines. -func CreateAnnotation(length int) string { - return fmt.Sprintf( - "%s%d", - annotationPrefix, - length, - ) -} - -// IsAnnotation determines whether the given line is an annotation created with CreateAnnotation. -func IsAnnotation(line string) bool { - return strings.HasPrefix( - strings.Trim(line, " \t"), - annotationPrefix, - ) -} - -// HasAnnotation determines whether the given AST node has a line length annotation on it. -func HasAnnotation(node dst.Node) bool { - startDecorations := node.Decorations().Start.All() - return len(startDecorations) > 0 && - IsAnnotation(startDecorations[len(startDecorations)-1]) -} - -// HasTailAnnotation determines whether the given AST node has a line length annotation at its -// end. This is needed to catch long function declarations with inline interface definitions. -func HasTailAnnotation(node dst.Node) bool { - endDecorations := node.Decorations().End.All() - return len(endDecorations) > 0 && - IsAnnotation(endDecorations[len(endDecorations)-1]) -} - -// HasAnnotationRecursive determines whether the given node or one of its children has a -// golines annotation on it. It's currently implemented for function declarations, fields, -// call expressions, and selector expressions only. -func HasAnnotationRecursive(node dst.Node) bool { - if HasAnnotation(node) { - return true - } - - switch n := node.(type) { - case *dst.FuncDecl: - if n.Type != nil && n.Type.Params != nil { - for _, item := range n.Type.Params.List { - if HasAnnotationRecursive(item) { - return true - } - } - } - case *dst.Field: - return HasTailAnnotation(n) || HasAnnotationRecursive(n.Type) - case *dst.SelectorExpr: - return HasAnnotation(n.Sel) || HasAnnotation(n.X) - case *dst.CallExpr: - if HasAnnotationRecursive(n.Fun) { - return true - } - - for _, arg := range n.Args { - if HasAnnotation(arg) { - return true - } - } - case *dst.InterfaceType: - for _, field := range n.Methods.List { - if HasAnnotationRecursive(field) { - return true - } - } - } - - return false -} - -// ParseAnnotation returns the line length encoded in a golines annotation. If none is found, -// it returns -1. -func ParseAnnotation(line string) int { - if IsAnnotation(line) { - components := strings.SplitN(line, ":", 3) - val, err := strconv.Atoi(components[2]) - if err != nil { - return -1 - } - return val - } - return -1 -} diff --git a/tools/vendor/github.com/golangci/golines/shorten/.gitattributes b/tools/vendor/github.com/golangci/golines/shorten/.gitattributes new file mode 100644 index 000000000..90fe9352e --- /dev/null +++ b/tools/vendor/github.com/golangci/golines/shorten/.gitattributes @@ -0,0 +1,3 @@ +/testdata/** text eol=lf +/internal/graph/testdata/** text eol=lf +/internal/comments/testdata/** text eol=lf diff --git a/tools/vendor/github.com/golangci/golines/shorten/annotations.go b/tools/vendor/github.com/golangci/golines/shorten/annotations.go new file mode 100644 index 000000000..0cba53fd6 --- /dev/null +++ b/tools/vendor/github.com/golangci/golines/shorten/annotations.go @@ -0,0 +1,65 @@ +package shorten + +import ( + "strings" + + "github.com/golangci/golines/shorten/internal" + "github.com/golangci/golines/shorten/internal/annotation" + "github.com/golangci/golines/shorten/internal/comments" +) + +// annotateLongLines adds specially formatted comments to all eligible lines that +// are longer than the configured target length. +// If a line already has one of these comments from a previous shortening round, +// then the comment contents are updated. +func (s *Shortener) annotateLongLines(lines []string) ([]string, int) { + var ( + annotatedLines []string + nbLinesToShorten int + ) + + prevLen := -1 + + for _, line := range lines { + length := internal.LineLength(line, s.config.TabLen) + + if prevLen > -1 { + if length <= s.config.MaxLen { + // Shortening successful, remove previous annotation + annotatedLines = annotatedLines[:len(annotatedLines)-1] + } else if length < prevLen { + // Replace annotation with a new length + annotatedLines[len(annotatedLines)-1] = annotation.Create(length) + + nbLinesToShorten++ + } + } else if !comments.Is(line) && length > s.config.MaxLen { + annotatedLines = append( + annotatedLines, + annotation.Create(length), + ) + + nbLinesToShorten++ + } + + annotatedLines = append(annotatedLines, line) + prevLen = annotation.Parse(line) + } + + return annotatedLines, nbLinesToShorten +} + +// removeAnnotations removes all comments added by the annotateLongLines function above. +func removeAnnotations(content []byte) []byte { + var cleanedLines []string + + lines := strings.SplitSeq(string(content), "\n") + + for line := range lines { + if !annotation.Is(line) { + cleanedLines = append(cleanedLines, line) + } + } + + return []byte(strings.Join(cleanedLines, "\n")) +} diff --git a/tools/vendor/github.com/golangci/golines/shorten/format.go b/tools/vendor/github.com/golangci/golines/shorten/format.go new file mode 100644 index 000000000..6c3abb67a --- /dev/null +++ b/tools/vendor/github.com/golangci/golines/shorten/format.go @@ -0,0 +1,339 @@ +package shorten + +import ( + "go/token" + "log/slog" + "reflect" + + "github.com/dave/dst" + "github.com/golangci/golines/shorten/internal/annotation" + "github.com/golangci/golines/shorten/internal/tags" +) + +// formatFile formats the provided AST file starting at the top-level declarations. +func (s *Shortener) formatFile(file *dst.File) { + for _, decl := range file.Decls { + s.formatNode(decl) + } +} + +// formatNode formats the provided AST node. +// The appropriate helper function is called based on +// whether the node is a declaration, expression, statement, or spec. +func (s *Shortener) formatNode(node dst.Node) { + switch n := node.(type) { + case dst.Decl: + s.logger.Debug("processing declaration", slog.Any("node", n)) + s.formatDecl(n) + + case dst.Expr: + s.logger.Debug("processing expression", slog.Any("node", n)) + s.formatExpr(n, false, false) + + case dst.Stmt: + s.logger.Debug("processing statement", slog.Any("node", n)) + s.formatStmt(n, false) + + case dst.Spec: + s.logger.Debug("processing spec", slog.Any("node", n)) + s.formatSpec(n, false) + + default: + s.logger.Debug( + "got a node type that can't be shortened", + slog.Any("node_type", reflect.TypeOf(n)), + ) + } +} + +// formatDecl formats an AST declaration node. +// These include function declarations, imports, and constants. +func (s *Shortener) formatDecl(decl dst.Decl) { + switch d := decl.(type) { + case *dst.FuncDecl: + if d.Type != nil && d.Type.Params != nil && annotation.HasRecursive(d) { + s.formatFieldList(d.Type.Params) + } + + s.formatStmt(d.Body, false) + + case *dst.GenDecl: + shouldShorten := annotation.Has(d) + + for _, spec := range d.Specs { + s.formatSpec(spec, shouldShorten) + } + + default: + s.logger.Debug( + "got a declaration type that can't be shortened", + slog.Any("decl_type", reflect.TypeOf(d)), + ) + } +} + +// formatStmt formats an AST statement node. +// Among other examples, these include assignments, case clauses, +// for statements, if statements, and select statements. +func (s *Shortener) formatStmt(stmt dst.Stmt, force bool) { + stmtType := reflect.TypeOf(stmt) + + // Explicitly check for nil statements + if reflect.ValueOf(stmt) == reflect.Zero(stmtType) { + return + } + + shouldShorten := force || annotation.Has(stmt) + + switch st := stmt.(type) { + case *dst.AssignStmt: + s.formatExprs(st.Rhs, shouldShorten, false) + + case *dst.BlockStmt: + s.formatStmts(st.List, false) + + case *dst.CaseClause: + if shouldShorten { + for _, arg := range st.List { + arg.Decorations().After = dst.NewLine + + s.formatExpr(arg, false, false) + } + } + + s.formatStmts(st.Body, false) + + case *dst.CommClause: + s.formatStmts(st.Body, false) + + case *dst.DeclStmt: + s.formatDecl(st.Decl) + + case *dst.DeferStmt: + s.formatExpr(st.Call, shouldShorten, false) + + case *dst.ExprStmt: + s.formatExpr(st.X, shouldShorten, false) + + case *dst.ForStmt: + s.formatStmt(st.Body, false) + + case *dst.GoStmt: + s.formatExpr(st.Call, shouldShorten, false) + + case *dst.IfStmt: + s.formatExpr(st.Cond, shouldShorten, false) + s.formatStmt(st.Body, false) + + if st.Init != nil { + s.formatStmt(st.Init, shouldShorten) + } + + if st.Else != nil { + s.formatStmt(st.Else, shouldShorten) + } + + case *dst.RangeStmt: + s.formatStmt(st.Body, false) + + case *dst.ReturnStmt: + s.formatExprs(st.Results, shouldShorten, false) + + case *dst.SelectStmt: + s.formatStmt(st.Body, false) + + case *dst.SwitchStmt: + s.formatStmt(st.Body, false) + + case *dst.TypeSwitchStmt: + s.formatStmt(st.Body, false) + + case *dst.BadStmt, *dst.EmptyStmt, *dst.LabeledStmt, + *dst.SendStmt, *dst.IncDecStmt, *dst.BranchStmt: + // These statements are explicitly defined to improve switch cases exhaustiveness. + // They may be handled in the future. + if shouldShorten { + s.logger.Debug( + "got a statement type that is not shortened", + slog.Any("stmt_type", stmtType), + ) + } + + default: + if shouldShorten { + s.logger.Debug( + "got an unknown statement type", + slog.Any("stmt_type", stmtType), + ) + } + } +} + +// formatExpr formats an AST expression node. +// These include uniary and binary expressions, function literals, +// and key/value pair statements, among others. +func (s *Shortener) formatExpr(expr dst.Expr, force, isChain bool) { + shouldShorten := force || annotation.Has(expr) + + switch e := expr.(type) { + case *dst.BinaryExpr: + if (e.Op == token.LAND || e.Op == token.LOR) && shouldShorten { + if e.Y.Decorations().Before == dst.NewLine { + s.formatExpr(e.X, force, isChain) + } else { + e.Y.Decorations().Before = dst.NewLine + } + } else { + s.formatExpr(e.X, shouldShorten, isChain) + s.formatExpr(e.Y, shouldShorten, isChain) + } + + case *dst.CallExpr: + shortenChildArgs := shouldShorten || annotation.HasRecursive(e) + + _, ok := e.Fun.(*dst.SelectorExpr) + + if ok && shortenChildArgs && + s.config.ChainSplitDots && (isChain || chainLength(e) > 1) { + e.Decorations().After = dst.NewLine + + s.formatExprs(e.Args, false, true) + s.formatExpr(e.Fun, shouldShorten, true) + } else { + for i, arg := range e.Args { + if shortenChildArgs { + formatList(arg, i) + } + + s.formatExpr(arg, false, isChain) + } + + s.formatExpr(e.Fun, shouldShorten, isChain) + } + + case *dst.CompositeLit: + if shouldShorten { + for i, element := range e.Elts { + if i == 0 { + element.Decorations().Before = dst.NewLine + } + + element.Decorations().After = dst.NewLine + } + } + + s.formatExprs(e.Elts, false, isChain) + + case *dst.FuncLit: + s.formatStmt(e.Body, false) + + case *dst.FuncType: + if shouldShorten { + s.formatFieldList(e.Params) + } + + case *dst.InterfaceType: + for _, method := range e.Methods.List { + if annotation.Has(method) { + s.formatExpr(method.Type, true, isChain) + } + } + + case *dst.KeyValueExpr: + s.formatExpr(e.Value, shouldShorten, isChain) + + case *dst.SelectorExpr: + s.formatExpr(e.X, shouldShorten, isChain) + + case *dst.StructType: + if s.config.ReformatTags { + tags.FormatStructTags(e.Fields) + } + + case *dst.UnaryExpr: + s.formatExpr(e.X, shouldShorten, isChain) + + default: + if shouldShorten { + s.logger.Debug( + "got an expression type that can't be shortened", + slog.Any("expr_type", reflect.TypeOf(e)), + ) + } + } +} + +// formatSpec formats an AST spec node. +// These include type specifications, among other things. +func (s *Shortener) formatSpec(spec dst.Spec, force bool) { + shouldShorten := annotation.Has(spec) || force + + switch sp := spec.(type) { + case *dst.ValueSpec: + s.formatExprs(sp.Values, shouldShorten, false) + + case *dst.TypeSpec: + s.formatExpr(sp.Type, false, false) + + default: + if shouldShorten { + s.logger.Debug( + "got a spec type that can't be shortened", + slog.Any("spec_type", reflect.TypeOf(sp)), + ) + } + } +} + +func (s *Shortener) formatStmts(stmts []dst.Stmt, force bool) { + for _, stmt := range stmts { + s.formatStmt(stmt, force) + } +} + +func (s *Shortener) formatExprs(exprs []dst.Expr, force, isChain bool) { + for _, expr := range exprs { + s.formatExpr(expr, force, isChain) + } +} + +// formatFieldList formats a field list in a function declaration. +func (s *Shortener) formatFieldList(fieldList *dst.FieldList) { + for i, field := range fieldList.List { + formatList(field, i) + } +} + +func formatList(node dst.Node, index int) { + decorations := node.Decorations() + + if index == 0 { + decorations.Before = dst.NewLine + } else { + decorations.Before = dst.None + } + + decorations.After = dst.NewLine +} + +// chainLength determines the length of the function call chain in an expression. +func chainLength(callExpr *dst.CallExpr) int { + numCalls := 1 + currCall := callExpr + + for { + selectorExpr, ok := currCall.Fun.(*dst.SelectorExpr) + if !ok { + break + } + + currCall, ok = selectorExpr.X.(*dst.CallExpr) + if !ok { + break + } + + numCalls++ + } + + return numCalls +} diff --git a/tools/vendor/github.com/golangci/golines/shorten/internal/annotation/annotation.go b/tools/vendor/github.com/golangci/golines/shorten/internal/annotation/annotation.go new file mode 100644 index 000000000..8491b4e46 --- /dev/null +++ b/tools/vendor/github.com/golangci/golines/shorten/internal/annotation/annotation.go @@ -0,0 +1,91 @@ +package annotation + +import ( + "fmt" + "slices" + "strconv" + "strings" + + "github.com/dave/dst" +) + +const prefix = "//golines:shorten:" + +// Create generates the text of a comment that will annotate long lines. +func Create(length int) string { + return fmt.Sprintf("%s%d", prefix, length) +} + +// Is determines whether the given line is an annotation created with Create. +func Is(line string) bool { + return strings.HasPrefix( + strings.Trim(line, " \t"), + prefix, + ) +} + +// Has determines whether the given AST node has a line length annotation on it. +func Has[T dst.Node](node T) bool { + return has(node.Decorations().Start) +} + +// HasTail determines whether the given AST node has a line length annotation at its end. +// This is needed to catch long function declarations with inline interface definitions. +func HasTail(node dst.Node) bool { + return has(node.Decorations().End) +} + +// HasRecursive determines whether the given node or one of its children has a +// golines annotation on it. It's currently implemented for function declarations, fields, +// call expressions, and selector expressions only. +func HasRecursive[T dst.Node](node T) bool { + if Has(node) { + return true + } + + switch n := any(node).(type) { + case *dst.FuncDecl: + return n.Type != nil && n.Type.Params != nil && + HasRecursive(n.Type.Params) + + case *dst.Field: + return HasTail(n) || HasRecursive(n.Type) + + case *dst.SelectorExpr: + return Has(n.Sel) || Has(n.X) + + case *dst.CallExpr: + return HasRecursive(n.Fun) || slices.ContainsFunc(n.Args, Has) + + case *dst.InterfaceType: + return HasRecursive(n.Methods) + + case *dst.FieldList: + return slices.ContainsFunc(n.List, HasRecursive) + } + + return false +} + +// Parse returns the line length encoded in a golines annotation. +// If none is found, it returns -1. +func Parse(line string) int { + if !Is(line) { + return -1 + } + + components := strings.SplitN(line, ":", 3) + + val, err := strconv.Atoi(components[2]) + if err != nil { + return -1 + } + + return val +} + +func has(decorations dst.Decorations) bool { + deco := decorations.All() + + return len(deco) > 0 && Is(deco[len(deco)-1]) +} diff --git a/tools/vendor/github.com/golangci/golines/shorten/internal/comments/comments.go b/tools/vendor/github.com/golangci/golines/shorten/internal/comments/comments.go new file mode 100644 index 000000000..5fd0e202a --- /dev/null +++ b/tools/vendor/github.com/golangci/golines/shorten/internal/comments/comments.go @@ -0,0 +1,104 @@ +package comments + +import ( + "fmt" + "regexp" + "strings" + + "github.com/golangci/golines/shorten/internal" + "github.com/golangci/golines/shorten/internal/annotation" +) + +// Shortener is a struct that can be used to shorten long comments. +// +// As noted in the repo README, +// this functionality has some quirks and is disabled by default. +type Shortener struct { + MaxLen int + TabLen int +} + +// Go directive (should be ignored). +// https://go.dev/doc/comment#syntax +var directivePattern = regexp.MustCompile(`\s*//(line |extern |export |[a-z0-9]+:[a-z0-9])`) + +// Process attempts to shorten long comments in the provided source. +// +// As noted in the repo README, +// this functionality has some quirks and is disabled by default. +func (s *Shortener) Process(content []byte) []byte { + if len(content) == 0 { + return content + } + + var cleanedLines []string + + // all words in a contiguous sequence of long comments + var words []string + + prefix := "" + + lines := strings.SplitSeq(string(content), "\n") + for line := range lines { + if Is(line) && !annotation.Is(line) && + !isDirective(line) && + internal.LineLength(line, s.TabLen) > s.MaxLen { + start := strings.Index(line, "//") + prefix = line[0:(start + 2)] + trimmedLine := strings.Trim(line[(start+2):], " ") + currLineWords := strings.Split(trimmedLine, " ") + words = append(words, currLineWords...) + } else { + // Reflow the accumulated `words` before appending the unprocessed `line`. + currLineLen := 0 + + var currLineWords []string + + maxCommentLen := s.MaxLen - internal.LineLength(prefix, s.TabLen) + for _, word := range words { + if currLineLen > 0 && currLineLen+1+len(word) > maxCommentLen { + cleanedLines = append( + cleanedLines, + fmt.Sprintf( + "%s %s", + prefix, + strings.Join(currLineWords, " "), + ), + ) + currLineWords = []string{} + currLineLen = 0 + } + + currLineWords = append(currLineWords, word) + currLineLen += 1 + len(word) + } + + if currLineLen > 0 { + cleanedLines = append( + cleanedLines, + fmt.Sprintf( + "%s %s", + prefix, + strings.Join(currLineWords, " "), + ), + ) + } + + words = []string{} + + cleanedLines = append(cleanedLines, line) + } + } + + return []byte(strings.Join(cleanedLines, "\n")) +} + +// Is determines whether the provided line is a non-block comment. +func Is(line string) bool { + return strings.HasPrefix(strings.Trim(line, " \t"), "//") +} + +// isDirective determines whether the provided line is a directive, e.g., for `go:generate`. +func isDirective(line string) bool { + return directivePattern.MatchString(line) +} diff --git a/tools/vendor/github.com/golangci/golines/shorten/internal/graph/graph.go b/tools/vendor/github.com/golangci/golines/shorten/internal/graph/graph.go new file mode 100644 index 000000000..e11eab9dd --- /dev/null +++ b/tools/vendor/github.com/golangci/golines/shorten/internal/graph/graph.go @@ -0,0 +1,132 @@ +package graph + +import ( + "fmt" + "html" + "io" + "strings" + + "github.com/dave/dst" + "github.com/golangci/golines/shorten/internal/annotation" +) + +// Node is a representation of a node in the AST graph. +type Node struct { + Type string + Value string + Node dst.Node + Edges []*Edge + + // Used for keeping track of node position during rendering + level int + seq int +} + +func (n *Node) id() string { + return fmt.Sprintf("%s_%d_%d", n.Type, n.level, n.seq) +} + +// Edge is a representation of an edge in the AST graph. +type Edge struct { + Dest *Node + Relationship string +} + +// CreateDot creates a dot representation of the graph associated with a dst node. +func CreateDot(node dst.Node, out io.Writer) error { + root := NodeToGraphNode(node) + + dotGraph, err := Walk(root) + if err != nil { + return err + } + + _, err = out.Write([]byte(dotGraph)) + + return err +} + +// Walk walks the graph starting at the argument root and returns +// a graphviz (dot) representation. +func Walk(root *Node) (string, error) { + toProcess := []*Node{root} + + var processed []*Node + + outLines := []string{"digraph {"} + + var ( + currLevel int + currSeq int + ) + + // First, loop through the graph nodes to assign proper ids + + for len(toProcess) != 0 { + currNode := toProcess[0] + + if currNode.level > currLevel { + currLevel = currNode.level + currSeq = 0 + } + + currNode.seq = currSeq + currSeq++ + + processed = append(processed, currNode) + toProcess = toProcess[1:] + + for _, edge := range currNode.Edges { + edge.Dest.level = currLevel + 1 + toProcess = append(toProcess, edge.Dest) + } + } + + // Then, fill out the graph in dot format + for _, node := range processed { + var ( + nodeLabel string + nodeFormat string + ) + + if annotation.Has(node.Node) { + nodeFormat = ",penwidth=3.0" + } + + if node.Value != "" { + nodeLabel = fmt.Sprintf( + `%s
%s`, + node.Type, + html.EscapeString(node.Value), + ) + } else { + nodeLabel = node.Type + } + + outLines = append( + outLines, + fmt.Sprintf( + "\t"+`%s[label=<%s>,shape="box"%s]`, + node.id(), + nodeLabel, + nodeFormat, + ), + ) + + for _, edge := range node.Edges { + outLines = append( + outLines, + fmt.Sprintf( + "\t"+`%s->%s[label="%s",fontsize=12.0]`, + node.id(), + edge.Dest.id(), + edge.Relationship, + ), + ) + } + } + + outLines = append(outLines, "}") + + return strings.Join(outLines, "\n"), nil +} diff --git a/tools/vendor/github.com/golangci/golines/shorten/internal/graph/graph_generated.go b/tools/vendor/github.com/golangci/golines/shorten/internal/graph/graph_generated.go new file mode 100644 index 000000000..40fa188bb --- /dev/null +++ b/tools/vendor/github.com/golangci/golines/shorten/internal/graph/graph_generated.go @@ -0,0 +1,596 @@ +// Code generated by 'generate/main.go.'; DO NOT EDIT. + +package graph + +import ( + dst "github.com/dave/dst" + "log" +) + +func NodeToGraphNode(node dst.Node) *Node { + gNode := &Node{Node: node, Edges: []*Edge{}} + var child *Node + switch n := node.(type) { + case *dst.ArrayType: + gNode.Type = "ArrayType" + if n.Len != nil { + child = NodeToGraphNode(n.Len) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Len"}) + } + if n.Elt != nil { + child = NodeToGraphNode(n.Elt) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Elt"}) + } + + case *dst.AssignStmt: + gNode.Type = "AssignStmt" + if n.Lhs != nil { + for _, obj := range n.Lhs { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Lhs"}) + } + } + if n.Rhs != nil { + for _, obj := range n.Rhs { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Rhs"}) + } + } + + case *dst.BadDecl: + gNode.Type = "BadDecl" + + case *dst.BadExpr: + gNode.Type = "BadExpr" + + case *dst.BadStmt: + gNode.Type = "BadStmt" + + case *dst.BasicLit: + gNode.Type = "BasicLit" + gNode.Value = n.Value + + case *dst.BinaryExpr: + gNode.Type = "BinaryExpr" + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + if n.Y != nil { + child = NodeToGraphNode(n.Y) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Y"}) + } + + case *dst.BlockStmt: + gNode.Type = "BlockStmt" + if n.List != nil { + for _, obj := range n.List { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "List"}) + } + } + + case *dst.BranchStmt: + gNode.Type = "BranchStmt" + if n.Label != nil { + child = NodeToGraphNode(n.Label) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Label"}) + } + + case *dst.CallExpr: + gNode.Type = "CallExpr" + if n.Fun != nil { + child = NodeToGraphNode(n.Fun) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Fun"}) + } + if n.Args != nil { + for _, obj := range n.Args { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Args"}) + } + } + + case *dst.CaseClause: + gNode.Type = "CaseClause" + if n.List != nil { + for _, obj := range n.List { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "List"}) + } + } + if n.Body != nil { + for _, obj := range n.Body { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Body"}) + } + } + + case *dst.ChanType: + gNode.Type = "ChanType" + if n.Value != nil { + child = NodeToGraphNode(n.Value) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Value"}) + } + + case *dst.CommClause: + gNode.Type = "CommClause" + if n.Comm != nil { + child = NodeToGraphNode(n.Comm) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Comm"}) + } + if n.Body != nil { + for _, obj := range n.Body { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Body"}) + } + } + + case *dst.CompositeLit: + gNode.Type = "CompositeLit" + if n.Type != nil { + child = NodeToGraphNode(n.Type) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Type"}) + } + if n.Elts != nil { + for _, obj := range n.Elts { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Elts"}) + } + } + + case *dst.DeclStmt: + gNode.Type = "DeclStmt" + if n.Decl != nil { + child = NodeToGraphNode(n.Decl) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Decl"}) + } + + case *dst.DeferStmt: + gNode.Type = "DeferStmt" + if n.Call != nil { + child = NodeToGraphNode(n.Call) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Call"}) + } + + case *dst.Ellipsis: + gNode.Type = "Ellipsis" + if n.Elt != nil { + child = NodeToGraphNode(n.Elt) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Elt"}) + } + + case *dst.EmptyStmt: + gNode.Type = "EmptyStmt" + + case *dst.ExprStmt: + gNode.Type = "ExprStmt" + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + + case *dst.Field: + gNode.Type = "Field" + if n.Names != nil { + for _, obj := range n.Names { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Names"}) + } + } + if n.Type != nil { + child = NodeToGraphNode(n.Type) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Type"}) + } + if n.Tag != nil { + child = NodeToGraphNode(n.Tag) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Tag"}) + } + + case *dst.FieldList: + gNode.Type = "FieldList" + if n.List != nil { + for _, obj := range n.List { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "List"}) + } + } + + case *dst.File: + gNode.Type = "File" + if n.Name != nil { + child = NodeToGraphNode(n.Name) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Name"}) + } + if n.Decls != nil { + for _, obj := range n.Decls { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Decls"}) + } + } + if n.Imports != nil { + for _, obj := range n.Imports { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Imports"}) + } + } + + case *dst.ForStmt: + gNode.Type = "ForStmt" + if n.Init != nil { + child = NodeToGraphNode(n.Init) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Init"}) + } + if n.Cond != nil { + child = NodeToGraphNode(n.Cond) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Cond"}) + } + if n.Post != nil { + child = NodeToGraphNode(n.Post) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Post"}) + } + if n.Body != nil { + child = NodeToGraphNode(n.Body) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Body"}) + } + + case *dst.FuncDecl: + gNode.Type = "FuncDecl" + if n.Recv != nil { + child = NodeToGraphNode(n.Recv) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Recv"}) + } + if n.Name != nil { + child = NodeToGraphNode(n.Name) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Name"}) + } + if n.Type.TypeParams != nil { + child = NodeToGraphNode(n.Type.TypeParams) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "TypeParams"}) + } + if n.Type.Params != nil { + child = NodeToGraphNode(n.Type.Params) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Params"}) + } + if n.Type.Results != nil { + child = NodeToGraphNode(n.Type.Results) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Results"}) + } + if n.Body != nil { + child = NodeToGraphNode(n.Body) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Body"}) + } + + case *dst.FuncLit: + gNode.Type = "FuncLit" + if n.Type != nil { + child = NodeToGraphNode(n.Type) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Type"}) + } + if n.Body != nil { + child = NodeToGraphNode(n.Body) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Body"}) + } + + case *dst.FuncType: + gNode.Type = "FuncType" + if n.TypeParams != nil { + child = NodeToGraphNode(n.TypeParams) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "TypeParams"}) + } + if n.Params != nil { + child = NodeToGraphNode(n.Params) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Params"}) + } + if n.Results != nil { + child = NodeToGraphNode(n.Results) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Results"}) + } + + case *dst.GenDecl: + gNode.Type = "GenDecl" + if n.Specs != nil { + for _, obj := range n.Specs { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Specs"}) + } + } + + case *dst.GoStmt: + gNode.Type = "GoStmt" + if n.Call != nil { + child = NodeToGraphNode(n.Call) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Call"}) + } + + case *dst.Ident: + gNode.Type = "Ident" + gNode.Value = n.Name + + case *dst.IfStmt: + gNode.Type = "IfStmt" + if n.Init != nil { + child = NodeToGraphNode(n.Init) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Init"}) + } + if n.Cond != nil { + child = NodeToGraphNode(n.Cond) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Cond"}) + } + if n.Body != nil { + child = NodeToGraphNode(n.Body) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Body"}) + } + if n.Else != nil { + child = NodeToGraphNode(n.Else) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Else"}) + } + + case *dst.ImportSpec: + gNode.Type = "ImportSpec" + if n.Name != nil { + child = NodeToGraphNode(n.Name) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Name"}) + } + if n.Path != nil { + child = NodeToGraphNode(n.Path) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Path"}) + } + + case *dst.IncDecStmt: + gNode.Type = "IncDecStmt" + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + + case *dst.IndexExpr: + gNode.Type = "IndexExpr" + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + if n.Index != nil { + child = NodeToGraphNode(n.Index) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Index"}) + } + + case *dst.IndexListExpr: + gNode.Type = "IndexListExpr" + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + if n.Indices != nil { + for _, obj := range n.Indices { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Indices"}) + } + } + + case *dst.InterfaceType: + gNode.Type = "InterfaceType" + if n.Methods != nil { + child = NodeToGraphNode(n.Methods) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Methods"}) + } + + case *dst.KeyValueExpr: + gNode.Type = "KeyValueExpr" + if n.Key != nil { + child = NodeToGraphNode(n.Key) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Key"}) + } + if n.Value != nil { + child = NodeToGraphNode(n.Value) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Value"}) + } + + case *dst.LabeledStmt: + gNode.Type = "LabeledStmt" + if n.Label != nil { + child = NodeToGraphNode(n.Label) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Label"}) + } + if n.Stmt != nil { + child = NodeToGraphNode(n.Stmt) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Stmt"}) + } + + case *dst.MapType: + gNode.Type = "MapType" + if n.Key != nil { + child = NodeToGraphNode(n.Key) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Key"}) + } + if n.Value != nil { + child = NodeToGraphNode(n.Value) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Value"}) + } + + case *dst.Package: + gNode.Type = "Package" + + case *dst.ParenExpr: + gNode.Type = "ParenExpr" + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + + case *dst.RangeStmt: + gNode.Type = "RangeStmt" + if n.Key != nil { + child = NodeToGraphNode(n.Key) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Key"}) + } + if n.Value != nil { + child = NodeToGraphNode(n.Value) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Value"}) + } + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + if n.Body != nil { + child = NodeToGraphNode(n.Body) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Body"}) + } + + case *dst.ReturnStmt: + gNode.Type = "ReturnStmt" + if n.Results != nil { + for _, obj := range n.Results { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Results"}) + } + } + + case *dst.SelectStmt: + gNode.Type = "SelectStmt" + if n.Body != nil { + child = NodeToGraphNode(n.Body) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Body"}) + } + + case *dst.SelectorExpr: + gNode.Type = "SelectorExpr" + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + if n.Sel != nil { + child = NodeToGraphNode(n.Sel) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Sel"}) + } + + case *dst.SendStmt: + gNode.Type = "SendStmt" + if n.Chan != nil { + child = NodeToGraphNode(n.Chan) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Chan"}) + } + if n.Value != nil { + child = NodeToGraphNode(n.Value) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Value"}) + } + + case *dst.SliceExpr: + gNode.Type = "SliceExpr" + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + if n.Low != nil { + child = NodeToGraphNode(n.Low) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Low"}) + } + if n.High != nil { + child = NodeToGraphNode(n.High) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "High"}) + } + if n.Max != nil { + child = NodeToGraphNode(n.Max) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Max"}) + } + + case *dst.StarExpr: + gNode.Type = "StarExpr" + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + + case *dst.StructType: + gNode.Type = "StructType" + if n.Fields != nil { + child = NodeToGraphNode(n.Fields) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Fields"}) + } + + case *dst.SwitchStmt: + gNode.Type = "SwitchStmt" + if n.Init != nil { + child = NodeToGraphNode(n.Init) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Init"}) + } + if n.Tag != nil { + child = NodeToGraphNode(n.Tag) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Tag"}) + } + if n.Body != nil { + child = NodeToGraphNode(n.Body) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Body"}) + } + + case *dst.TypeAssertExpr: + gNode.Type = "TypeAssertExpr" + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + if n.Type != nil { + child = NodeToGraphNode(n.Type) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Type"}) + } + + case *dst.TypeSpec: + gNode.Type = "TypeSpec" + if n.Name != nil { + child = NodeToGraphNode(n.Name) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Name"}) + } + if n.TypeParams != nil { + child = NodeToGraphNode(n.TypeParams) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "TypeParams"}) + } + if n.Type != nil { + child = NodeToGraphNode(n.Type) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Type"}) + } + + case *dst.TypeSwitchStmt: + gNode.Type = "TypeSwitchStmt" + if n.Init != nil { + child = NodeToGraphNode(n.Init) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Init"}) + } + if n.Assign != nil { + child = NodeToGraphNode(n.Assign) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Assign"}) + } + if n.Body != nil { + child = NodeToGraphNode(n.Body) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Body"}) + } + + case *dst.UnaryExpr: + gNode.Type = "UnaryExpr" + if n.X != nil { + child = NodeToGraphNode(n.X) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "X"}) + } + + case *dst.ValueSpec: + gNode.Type = "ValueSpec" + if n.Names != nil { + for _, obj := range n.Names { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Names"}) + } + } + if n.Type != nil { + child = NodeToGraphNode(n.Type) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Type"}) + } + if n.Values != nil { + for _, obj := range n.Values { + child = NodeToGraphNode(obj) + gNode.Edges = append(gNode.Edges, &Edge{Dest: child, Relationship: "Values"}) + } + } + + default: + log.Println("Unrecognized type") + } + return gNode +} diff --git a/tools/vendor/github.com/golangci/golines/shorten/internal/line.go b/tools/vendor/github.com/golangci/golines/shorten/internal/line.go new file mode 100644 index 000000000..a195469d6 --- /dev/null +++ b/tools/vendor/github.com/golangci/golines/shorten/internal/line.go @@ -0,0 +1,16 @@ +package internal + +// LineLength gets the width of the provided line after tab expansion. +func LineLength(line string, tabLen int) int { + length := 0 + + for _, char := range line { + if char == '\t' { + length += tabLen + } else { + length++ + } + } + + return length +} diff --git a/tools/vendor/github.com/golangci/golines/shorten/internal/tags/filler.go b/tools/vendor/github.com/golangci/golines/shorten/internal/tags/filler.go new file mode 100644 index 000000000..d5efe8737 --- /dev/null +++ b/tools/vendor/github.com/golangci/golines/shorten/internal/tags/filler.go @@ -0,0 +1,42 @@ +package tags + +import "fmt" + +type tagEntry struct { + Key string + Content string +} + +// filler is used to collect tags. +// It uses a slice to keep track of the tags in order of appearance. +type filler struct { + data []*tagEntry + + uniq map[string]*tagEntry +} + +func newFiller() *filler { + return &filler{ + uniq: map[string]*tagEntry{}, + } +} + +func (f *filler) Data() []*tagEntry { + return f.data +} + +func (f *filler) Fill(key, value string) error { + if e, ok := f.uniq[key]; ok { + e.Content += " " + fmt.Sprintf("%s:%q", key, value) + } else { + entry := &tagEntry{ + Key: key, + Content: fmt.Sprintf("%s:%q", key, value), + } + + f.uniq[key] = entry + f.data = append(f.data, entry) + } + + return nil +} diff --git a/tools/vendor/github.com/golangci/golines/tags.go b/tools/vendor/github.com/golangci/golines/shorten/internal/tags/tags.go similarity index 59% rename from tools/vendor/github.com/golangci/golines/tags.go rename to tools/vendor/github.com/golangci/golines/shorten/internal/tags/tags.go index f5321fab4..ef9305b88 100644 --- a/tools/vendor/github.com/golangci/golines/tags.go +++ b/tools/vendor/github.com/golangci/golines/shorten/internal/tags/tags.go @@ -1,27 +1,23 @@ -package golines +package tags import ( "fmt" - "reflect" "regexp" + "slices" "strings" + "unicode/utf8" "github.com/dave/dst" - "github.com/fatih/structtag" + "github.com/golangci/golines/shorten/internal/annotation" + "github.com/ldez/structtags/parser" ) var structTagRegexp = regexp.MustCompile("`([ ]*[a-zA-Z0-9_-]+:\".*\"[ ]*){2,}`") -// HasMultiKeyTags returns whether the given lines have a multikey struct line. -// It's used as an optimization step to avoid unnnecessary shortening rounds. -func HasMultiKeyTags(lines []string) bool { - for _, line := range lines { - if structTagRegexp.MatchString(line) { - return true - } - } - - return false +// HasMultipleEntries returns whether the given lines have a multi-entries struct line. +// It's used as an optimization step to avoid unnecessary shortening rounds. +func HasMultipleEntries(lines []string) bool { + return slices.ContainsFunc(lines, structTagRegexp.MatchString) } // FormatStructTags formats struct tags so that the keys within each block of fields are aligned. @@ -34,35 +30,54 @@ func FormatStructTags(fieldList *dst.FieldList) { return } - blockFields := []*dst.Field{} + var blockFields []*dst.Field + + // Divide fields into "blocks" so that we don't do alignments across blank lines and comments. + for _, field := range fieldList.List { + if isEndFieldsBlock(field) { + align(blockFields) - // Divide fields into "blocks" so that we don't do alignments across blank lines - for f, field := range fieldList.List { - if f == 0 || field.Decorations().Before == dst.EmptyLine { - alignTags(blockFields) blockFields = blockFields[:0] } blockFields = append(blockFields, field) } - alignTags(blockFields) + align(blockFields) +} + +func isEndFieldsBlock(field *dst.Field) bool { + return field.Decorations().Before == dst.EmptyLine || + slices.ContainsFunc(field.Decorations().Start.All(), func(s string) bool { + return !annotation.Is(s) + }) } -// alignTags formats the struct tags within a single field block. -func alignTags(fields []*dst.Field) { +// align formats the struct tags within a single field block. +// NOTE(ldez): all the code of `align` is not related to shorten, +// instead of shortening a line, it increases the line length. +// It must be either: +// - disabled by default +// - or the additional spaces should be an option +// - or maybe removed. +func align(fields []*dst.Field) { if len(fields) == 0 { return } maxTagWidths := map[string]int{} - tagKeys := []string{} + + var tagKeys []string + tagKVs := make([]map[string]string, len(fields)) - maxTypeWidth := 0 - invalidWidths := false + var ( + maxTypeWidth int + invalidWidths bool + ) // First, scan over all field tags so that we can understand their values and widths + for f, field := range fields { if len(field.Names) > 0 { typeWidth, err := getWidth(field.Type) @@ -84,34 +99,30 @@ func alignTags(fields []*dst.Field) { if tagValue[0] != '`' || tagValue[len(tagValue)-1] != '`' { continue } + tagValue = tagValue[1 : len(tagValue)-1] - subTags, err := structtag.Parse(tagValue) + entries, err := parser.Tag(tagValue, newFiller()) if err != nil { return } - subTagKeys := subTags.Keys() - - structTag := reflect.StructTag(tagValue) - - for _, key := range subTagKeys { - value := structTag.Get(key) + for _, entry := range entries { // Tag is key, value, and some extra chars (two quotes + one colon) - width := len(key) + tagValueLen(value) + 3 + width := utf8.RuneCountInString(entry.Content) - if _, ok := maxTagWidths[key]; !ok { - maxTagWidths[key] = width - tagKeys = append(tagKeys, key) - } else if width > maxTagWidths[key] { - maxTagWidths[key] = width + if _, ok := maxTagWidths[entry.Key]; !ok { + maxTagWidths[entry.Key] = width + tagKeys = append(tagKeys, entry.Key) + } else if width > maxTagWidths[entry.Key] { + maxTagWidths[entry.Key] = width } if tagKVs[f] == nil { tagKVs[f] = map[string]string{} } - tagKVs[f][key] = value + tagKVs[f][entry.Key] = entry.Content } } @@ -121,24 +132,22 @@ func alignTags(fields []*dst.Field) { continue } - tagComponents := []string{} + var tagComponents []string if len(field.Names) == 0 && maxTypeWidth > 0 && !invalidWidths { // Add extra spacing at beginning so that tag aligns with named field tags tagComponents = append(tagComponents, "") - for i := 0; i < maxTypeWidth; i++ { - tagComponents[len(tagComponents)-1] += " " - } + tagComponents[len(tagComponents)-1] += strings.Repeat(" ", maxTypeWidth) } for _, key := range tagKeys { - value, ok := tagKVs[f][key] + content, ok := tagKVs[f][key] lenUsed := 0 if ok { - tagComponents = append(tagComponents, fmt.Sprintf("%s:\"%s\"", key, value)) - lenUsed += len(key) + tagValueLen(value) + 3 + tagComponents = append(tagComponents, content) + lenUsed += utf8.RuneCountInString(content) } else { tagComponents = append(tagComponents, "") } @@ -146,25 +155,17 @@ func alignTags(fields []*dst.Field) { if len(field.Names) > 0 || !invalidWidths { lenRemaining := maxTagWidths[key] - lenUsed - for i := 0; i < lenRemaining; i++ { - tagComponents[len(tagComponents)-1] += " " - } + tagComponents[len(tagComponents)-1] += strings.Repeat(" ", lenRemaining) } } - updatedTagValue := strings.TrimRight(strings.Join(tagComponents, " "), " ") - field.Tag.Value = fmt.Sprintf("`%s`", updatedTagValue) + field.Tag.Value = fmt.Sprintf("`%s`", + strings.TrimRight(strings.Join(tagComponents, " "), " ")) } } -// get real tag value's length, fix multi-byte character's length, such as `ï` -// or `中文` -func tagValueLen(s string) int { - return len([]rune(s)) -} - -// getWidth tries to guess the formatted width of a dst node expression. If this isn't (yet) -// possible, it returns an error. +// getWidth tries to guess the formatted width of a dst node expression. +// If this isn't (yet) possible, it returns an error. func getWidth(node dst.Node) (int, error) { switch n := node.(type) { case *dst.ArrayType: @@ -174,6 +175,7 @@ func getWidth(node dst.Node) (int, error) { } return 2 + eltWidth, nil + case *dst.ChanType: valWidth, err := getWidth(n.Value) if err != nil { @@ -190,8 +192,10 @@ func getWidth(node dst.Node) (int, error) { // Channel includes an arrow return 7 + valWidth, nil + case *dst.Ident: return len(n.Name), nil + case *dst.MapType: keyWidth, err := getWidth(n.Key) if err != nil { @@ -204,6 +208,7 @@ func getWidth(node dst.Node) (int, error) { } return 5 + keyWidth + valWidth, nil + case *dst.StarExpr: xWidth, err := getWidth(n.X) if err != nil { @@ -213,5 +218,5 @@ func getWidth(node dst.Node) (int, error) { return 1 + xWidth, nil } - return 0, fmt.Errorf("Could not get width of node %+v", node) + return 0, fmt.Errorf("could not get the width of node %+v", node) } diff --git a/tools/vendor/github.com/golangci/golines/shorten/log.go b/tools/vendor/github.com/golangci/golines/shorten/log.go new file mode 100644 index 000000000..fe1827424 --- /dev/null +++ b/tools/vendor/github.com/golangci/golines/shorten/log.go @@ -0,0 +1,9 @@ +package shorten + +type Logger interface { + Debug(msg string, args ...any) +} + +type noopLogger struct{} + +func (n *noopLogger) Debug(_ string, _ ...any) {} diff --git a/tools/vendor/github.com/golangci/golines/shorten/shortener.go b/tools/vendor/github.com/golangci/golines/shorten/shortener.go new file mode 100644 index 000000000..413ce4c9d --- /dev/null +++ b/tools/vendor/github.com/golangci/golines/shorten/shortener.go @@ -0,0 +1,206 @@ +package shorten + +import ( + "bytes" + "fmt" + "go/format" + "log/slog" + "os" + "strings" + + "github.com/dave/dst" + "github.com/dave/dst/decorator" + "github.com/golangci/golines/shorten/internal/comments" + "github.com/golangci/golines/shorten/internal/graph" + "github.com/golangci/golines/shorten/internal/tags" +) + +// The maximum number of shortening "rounds" that we'll allow. +// The shortening process should converge quickly, +// but we have this here as a safety mechanism to prevent loops that prevent termination. +const maxRounds = 20 + +// Config stores the configuration options exposed by a Shortener instance. +type Config struct { + // MaxLen Max target width for each line + MaxLen int + + // TabLen Width of a tab character + TabLen int + + // KeepAnnotations Whether to keep annotations in the final result (for debugging only) + KeepAnnotations bool + + // ShortenComments Whether to shorten comments + ShortenComments bool + + // ReformatTags Whether to reformat struct tags in addition to shortening long lines + ReformatTags bool + + // DotFile Path to write dot-formatted output to (for debugging only) + DotFile string + + // ChainSplitDots Whether to split chain methods by putting dots at the ends of lines + ChainSplitDots bool +} + +// NewDefaultConfig returns a [Config] with default values. +func NewDefaultConfig() *Config { + return &Config{ + MaxLen: 100, + TabLen: 4, + KeepAnnotations: false, + ShortenComments: false, + ReformatTags: true, + DotFile: "", + ChainSplitDots: true, + } +} + +// Options is the type for configuring options of a [Shortener] instance. +type Options func(*Shortener) + +// WithLogger sets the logger to use it for a [Shortener] instance. +func WithLogger(logger Logger) Options { + return func(s *Shortener) { + if logger != nil { + s.logger = logger + } + } +} + +// Shortener shortens a single go file according to a small set of user style preferences. +type Shortener struct { + config *Config + + commentsShortener *comments.Shortener + + logger Logger +} + +// NewShortener creates a new shortener instance from the provided config. +func NewShortener(config *Config, opts ...Options) *Shortener { + if config == nil { + config = NewDefaultConfig() + } + + s := &Shortener{ + config: config, + logger: &noopLogger{}, + } + + if config.ShortenComments { + s.commentsShortener = &comments.Shortener{ + MaxLen: config.MaxLen, + TabLen: config.TabLen, + } + } + + for _, opt := range opts { + opt(s) + } + + return s +} + +// Process shortens the provided golang file content bytes. +func (s *Shortener) Process(content []byte) ([]byte, error) { + var round int + + var err error + + // Do initial, non-line-length-aware formatting + content, err = format.Source(content) + if err != nil { + return nil, fmt.Errorf("error formatting source: %w", err) + } + + for { + s.logger.Debug("starting round", slog.Int("round", round)) + + // Annotate all long lines + lines := strings.Split(string(content), "\n") + annotatedLines, nbLinesToShorten := s.annotateLongLines(lines) + + if !s.shouldContinue(nbLinesToShorten, round, lines) { + s.logger.Debug("nothing more to shorten or reformat, stopping") + + break + } + + content = []byte(strings.Join(annotatedLines, "\n")) + + // Generate AST + result, err := decorator.Parse(content) + if err != nil { + return nil, err + } + + if s.config.DotFile != "" { + err = s.createDot(result) + if err != nil { + return nil, err + } + } + + // Process the file. + s.formatFile(result) + + // Materialize output + output := bytes.NewBuffer([]byte{}) + + err = decorator.Fprint(output, result) + if err != nil { + return nil, fmt.Errorf("error parsing source: %w", err) + } + + content = output.Bytes() + + round++ + + if round > maxRounds { + s.logger.Debug("hit max rounds, stopping") + + break + } + } + + if !s.config.KeepAnnotations { + content = removeAnnotations(content) + } + + if s.commentsShortener != nil { + content = s.commentsShortener.Process(content) + } + + // Do the final round of non-line-length-aware formatting after we've fixed up the comments + content, err = format.Source(content) + if err != nil { + return nil, fmt.Errorf("error formatting source: %w", err) + } + + return content, nil +} + +// shouldContinue returns true: +// if there are lines to shorten, +// or if this is the first round (0), +// and the option to reformat struct tags is enabled, +// and there are struct tags with multiple entries. +func (s *Shortener) shouldContinue(nbLinesToShorten, round int, lines []string) bool { + return nbLinesToShorten > 0 || + round == 0 && s.config.ReformatTags && tags.HasMultipleEntries(lines) +} + +func (s *Shortener) createDot(result dst.Node) error { + dotFile, err := os.Create(s.config.DotFile) + if err != nil { + return err + } + + defer dotFile.Close() + + s.logger.Debug("writing dot file output", slog.String("file", s.config.DotFile)) + + return graph.CreateDot(result, dotFile) +} diff --git a/tools/vendor/github.com/golangci/golines/shortener.go b/tools/vendor/github.com/golangci/golines/shortener.go deleted file mode 100644 index c35b5f35b..000000000 --- a/tools/vendor/github.com/golangci/golines/shortener.go +++ /dev/null @@ -1,594 +0,0 @@ -package golines - -import ( - "bufio" - "bytes" - "fmt" - "go/format" - "go/token" - "os/exec" - "reflect" - "regexp" - "strings" - - "github.com/dave/dst" - "github.com/dave/dst/decorator" -) - -var ( - // Strings to look for to identify generated files - generatedTerms = []string{ - "do not edit", - "generated by", - "automatically regenerated", - } - // Go directives (should be ignored) - goDirectiveLine = regexp.MustCompile(`\s*//\s*go:.*`) -) - -// The maximum number of shortening "rounds" that we'll allow. The shortening -// process should converge quickly, but we have this here as a safety mechanism to -// prevent loops that prevent termination. -const maxRounds = 20 - -// ShortenerConfig stores the configuration options exposed by a Shortener instance. -type ShortenerConfig struct { - MaxLen int // Max target width for each line - TabLen int // Width of a tab character - KeepAnnotations bool // Whether to keep annotations in final result (for debugging only) - ShortenComments bool // Whether to shorten comments - ReformatTags bool // Whether to reformat struct tags in addition to shortening long lines - IgnoreGenerated bool // Whether to ignore generated files - DotFile string // Path to write dot-formatted output to (for debugging only) - ChainSplitDots bool // Whether to split chain methods by putting dots at ends of lines - - // Formatter that will be run before and after main shortening process. If empty, - // defaults to goimports (if found), otherwise gofmt. - BaseFormatterCmd string -} - -// Shortener shortens a single go file according to a small set of user style -// preferences. -type Shortener struct { - config ShortenerConfig - - // Some extra params around the base formatter generated from the BaseFormatterCmd - // argument in the config. - baseFormatter string - baseFormatterArgs []string -} - -// NewShortener creates a new shortener instance from the provided config. -func NewShortener(config ShortenerConfig) *Shortener { - var formatterComponents []string - - // golangci-lint: hardcoded base formatter. - // Note: - // - the command `gofmt` is not used, it calls `format.Source`. - // - the format is related to `go fmt` and not `gofmt`. - config.BaseFormatterCmd = "gofmt" - - if config.BaseFormatterCmd == "" { - _, err := exec.LookPath("goimports") - if err != nil { - formatterComponents = []string{"gofmt"} - } else { - formatterComponents = []string{"goimports"} - } - } else { - formatterComponents = strings.Split(config.BaseFormatterCmd, " ") - } - - s := &Shortener{ - config: config, - baseFormatter: formatterComponents[0], - } - - if len(formatterComponents) > 1 { - s.baseFormatterArgs = formatterComponents[1:] - } else { - s.baseFormatterArgs = []string{} - } - - return s -} - -// Shorten shortens the provided golang file content bytes. -func (s *Shortener) Shorten(contents []byte) ([]byte, error) { - if s.config.IgnoreGenerated && s.isGenerated(contents) { - return contents, nil - } - - round := 0 - var err error - - // Do initial, non-line-length-aware formatting - contents, err = s.formatSrc(contents) - if err != nil { - return nil, fmt.Errorf("Error formatting source: %+v", err) - } - - for { - // Annotate all long lines - lines := strings.Split(string(contents), "\n") - annotatedLines, linesToShorten := s.annotateLongLines(lines) - var stop bool - - if linesToShorten == 0 { - if round == 0 { - if !s.config.ReformatTags { - stop = true - } else if !HasMultiKeyTags(lines) { - stop = true - } - } else { - stop = true - } - } - - if stop { - break - } - - contents = []byte(strings.Join(annotatedLines, "\n")) - - // Generate AST - result, err := decorator.Parse(contents) - if err != nil { - return nil, err - } - - // Shorten the file starting at the top-level declarations - for _, decl := range result.Decls { - s.formatNode(decl) - } - - // Materialize output - output := bytes.NewBuffer([]byte{}) - err = decorator.Fprint(output, result) - if err != nil { - return nil, fmt.Errorf("Error parsing source: %+v", err) - } - contents = output.Bytes() - - round++ - - if round > maxRounds { - break - } - } - - if !s.config.KeepAnnotations { - contents = s.removeAnnotations(contents) - } - if s.config.ShortenComments { - contents = s.shortenCommentsFunc(contents) - } - - // Do final round of non-line-length-aware formatting after we've fixed up the comments - contents, err = s.formatSrc(contents) - if err != nil { - return nil, fmt.Errorf("Error formatting source: %+v", err) - } - - return contents, nil -} - -// formatSrc formats the provided source bytes using the configured "base" formatter (typically -// goimports or gofmt). -func (s *Shortener) formatSrc(contents []byte) ([]byte, error) { - if s.baseFormatter == "gofmt" { - return format.Source(contents) - } - - cmd := exec.Command(s.baseFormatter, s.baseFormatterArgs...) - stdinPipe, err := cmd.StdinPipe() - if err != nil { - return nil, err - } - - outBuffer := &bytes.Buffer{} - cmd.Stdout = outBuffer - - if err = cmd.Start(); err != nil { - return nil, err - } - - _, err = stdinPipe.Write(contents) - if err != nil { - return nil, err - } - stdinPipe.Close() - - err = cmd.Wait() - if err != nil { - return nil, err - } - - return outBuffer.Bytes(), nil -} - -// annotateLongLines adds specially-formatted comments to all eligible lines that are longer than -// the configured target length. If a line already has one of these comments from a previous -// shortening round, then the comment contents are updated. -func (s *Shortener) annotateLongLines(lines []string) ([]string, int) { - annotatedLines := []string{} - linesToShorten := 0 - prevLen := -1 - - for _, line := range lines { - length := s.lineLen(line) - - if prevLen > -1 { - if length <= s.config.MaxLen { - // Shortening successful, remove previous annotation - annotatedLines = annotatedLines[:len(annotatedLines)-1] - } else if length < prevLen { - // Replace annotation with new length - annotatedLines[len(annotatedLines)-1] = CreateAnnotation(length) - linesToShorten++ - } - } else if !s.isComment(line) && length > s.config.MaxLen { - annotatedLines = append( - annotatedLines, - CreateAnnotation(length), - ) - linesToShorten++ - } - - annotatedLines = append(annotatedLines, line) - prevLen = ParseAnnotation(line) - } - - return annotatedLines, linesToShorten -} - -// removeAnnotations removes all comments that were added by the annotateLongLines -// function above. -func (s *Shortener) removeAnnotations(contents []byte) []byte { - cleanedLines := []string{} - lines := strings.Split(string(contents), "\n") - - for _, line := range lines { - if !IsAnnotation(line) { - cleanedLines = append(cleanedLines, line) - } - } - - return []byte(strings.Join(cleanedLines, "\n")) -} - -// shortenCommentsFunc attempts to shorten long comments in the provided source. As noted -// in the repo README, this functionality has some quirks and is disabled by default. -func (s *Shortener) shortenCommentsFunc(contents []byte) []byte { - cleanedLines := []string{} - words := []string{} // all words in a contiguous sequence of long comments - prefix := "" - lines := strings.Split(string(contents), "\n") - for _, line := range lines { - if s.isComment(line) && !IsAnnotation(line) && - !s.isGoDirective(line) && - s.lineLen(line) > s.config.MaxLen { - start := strings.Index(line, "//") - prefix = line[0:(start + 2)] - trimmedLine := strings.Trim(line[(start+2):], " ") - currLineWords := strings.Split(trimmedLine, " ") - words = append(words, currLineWords...) - } else { - // Reflow the accumulated `words` before appending the unprocessed `line`. - currLineLen := 0 - currLineWords := []string{} - maxCommentLen := s.config.MaxLen - s.lineLen(prefix) - for _, word := range words { - if currLineLen > 0 && currLineLen+1+len(word) > maxCommentLen { - cleanedLines = append( - cleanedLines, - fmt.Sprintf( - "%s %s", - prefix, - strings.Join(currLineWords, " "), - ), - ) - currLineWords = []string{} - currLineLen = 0 - } - currLineWords = append(currLineWords, word) - currLineLen += 1 + len(word) - } - if currLineLen > 0 { - cleanedLines = append( - cleanedLines, - fmt.Sprintf( - "%s %s", - prefix, - strings.Join(currLineWords, " "), - ), - ) - } - words = []string{} - - cleanedLines = append(cleanedLines, line) - } - } - return []byte(strings.Join(cleanedLines, "\n")) -} - -// lineLen gets the width of the provided line after tab expansion. -func (s *Shortener) lineLen(line string) int { - length := 0 - - for _, char := range line { - if char == '\t' { - length += s.config.TabLen - } else { - length++ - } - } - - return length -} - -// isComment determines whether the provided line is a non-block comment. -func (s *Shortener) isComment(line string) bool { - return strings.HasPrefix(strings.Trim(line, " \t"), "//") -} - -// isGoDirective determines whether the provided line is a go directive, e.g. for go generate. -func (s *Shortener) isGoDirective(line string) bool { - return goDirectiveLine.MatchString(line) -} - -// formatNode formats the provided AST node. The appropriate helper function is called -// based on whether the node is a declaration, expression, statement, or spec. -func (s *Shortener) formatNode(node dst.Node) { - switch n := node.(type) { - case dst.Decl: - s.formatDecl(n) - case dst.Expr: - s.formatExpr(n, false, false) - case dst.Stmt: - s.formatStmt(n) - case dst.Spec: - s.formatSpec(n, false) - default: - // noop - } -} - -// formatDecl formats an AST declaration node. These include function declarations, -// imports, and constants. -func (s *Shortener) formatDecl(decl dst.Decl) { - switch d := decl.(type) { - case *dst.FuncDecl: - if HasAnnotationRecursive(decl) { - if d.Type != nil && d.Type.Params != nil { - s.formatFieldList(d.Type.Params) - } - } - s.formatStmt(d.Body) - case *dst.GenDecl: - for _, spec := range d.Specs { - s.formatSpec(spec, HasAnnotation(decl)) - } - default: - // noop - } -} - -// formatFieldList formats a field list in a function declaration. -func (s *Shortener) formatFieldList(fieldList *dst.FieldList) { - for f, field := range fieldList.List { - if f == 0 { - field.Decorations().Before = dst.NewLine - } else { - field.Decorations().Before = dst.None - } - - field.Decorations().After = dst.NewLine - } -} - -// formatStmt formats an AST statement node. Among other examples, these include assignments, -// case clauses, for statements, if statements, and select statements. -func (s *Shortener) formatStmt(stmt dst.Stmt) { - // Explicitly check for nil statements - stmtType := reflect.TypeOf(stmt) - if reflect.ValueOf(stmt) == reflect.Zero(stmtType) { - return - } - - shouldShorten := HasAnnotation(stmt) - - switch st := stmt.(type) { - case *dst.AssignStmt: - for _, expr := range st.Rhs { - s.formatExpr(expr, shouldShorten, false) - } - case *dst.BlockStmt: - for _, stmt := range st.List { - s.formatStmt(stmt) - } - case *dst.CaseClause: - if shouldShorten { - for _, arg := range st.List { - arg.Decorations().After = dst.NewLine - s.formatExpr(arg, false, false) - } - } - - for _, stmt := range st.Body { - s.formatStmt(stmt) - } - case *dst.CommClause: - for _, stmt := range st.Body { - s.formatStmt(stmt) - } - case *dst.DeclStmt: - s.formatDecl(st.Decl) - case *dst.DeferStmt: - s.formatExpr(st.Call, shouldShorten, false) - case *dst.ExprStmt: - s.formatExpr(st.X, shouldShorten, false) - case *dst.ForStmt: - s.formatStmt(st.Body) - case *dst.GoStmt: - s.formatExpr(st.Call, shouldShorten, false) - case *dst.IfStmt: - s.formatExpr(st.Cond, shouldShorten, false) - s.formatStmt(st.Body) - case *dst.RangeStmt: - s.formatStmt(st.Body) - case *dst.ReturnStmt: - for _, expr := range st.Results { - s.formatExpr(expr, shouldShorten, false) - } - case *dst.SelectStmt: - s.formatStmt(st.Body) - case *dst.SwitchStmt: - s.formatStmt(st.Body) - default: - // noop - } -} - -// formatExpr formats an AST expression node. These include uniary and binary expressions, function -// literals, and key/value pair statements, among others. -func (s *Shortener) formatExpr(expr dst.Expr, force bool, isChain bool) { - shouldShorten := force || HasAnnotation(expr) - - switch e := expr.(type) { - case *dst.BinaryExpr: - if (e.Op == token.LAND || e.Op == token.LOR) && shouldShorten { - if e.Y.Decorations().Before == dst.NewLine { - s.formatExpr(e.X, force, isChain) - } else { - e.Y.Decorations().Before = dst.NewLine - } - } else { - s.formatExpr(e.X, shouldShorten, isChain) - s.formatExpr(e.Y, shouldShorten, isChain) - } - case *dst.CallExpr: - _, ok := e.Fun.(*dst.SelectorExpr) - - if ok && - s.config.ChainSplitDots && - (shouldShorten || HasAnnotationRecursive(e)) && - (isChain || s.chainLength(e) > 1) { - e.Decorations().After = dst.NewLine - - for _, arg := range e.Args { - s.formatExpr(arg, false, true) - } - - s.formatExpr(e.Fun, shouldShorten, true) - } else { - shortenChildArgs := shouldShorten || HasAnnotationRecursive(e) - - for a, arg := range e.Args { - if shortenChildArgs { - if a == 0 { - arg.Decorations().Before = dst.NewLine - } else { - arg.Decorations().After = dst.None - } - arg.Decorations().After = dst.NewLine - } - s.formatExpr(arg, false, isChain) - } - s.formatExpr(e.Fun, shouldShorten, isChain) - } - case *dst.CompositeLit: - if shouldShorten { - for i, element := range e.Elts { - if i == 0 { - element.Decorations().Before = dst.NewLine - } - element.Decorations().After = dst.NewLine - } - } - - for _, element := range e.Elts { - s.formatExpr(element, false, isChain) - } - case *dst.FuncLit: - s.formatStmt(e.Body) - case *dst.FuncType: - if shouldShorten { - s.formatFieldList(e.Params) - } - case *dst.InterfaceType: - for _, method := range e.Methods.List { - if HasAnnotation(method) { - s.formatExpr(method.Type, true, isChain) - } - } - case *dst.KeyValueExpr: - s.formatExpr(e.Value, shouldShorten, isChain) - case *dst.SelectorExpr: - s.formatExpr(e.X, shouldShorten, isChain) - case *dst.StructType: - if s.config.ReformatTags { - FormatStructTags(e.Fields) - } - case *dst.UnaryExpr: - s.formatExpr(e.X, shouldShorten, isChain) - default: - // noop - } -} - -// formatSpec formats an AST spec node. These include type specifications, among other things. -func (s *Shortener) formatSpec(spec dst.Spec, force bool) { - shouldShorten := HasAnnotation(spec) || force - switch sp := spec.(type) { - case *dst.ValueSpec: - for _, expr := range sp.Values { - s.formatExpr(expr, shouldShorten, false) - } - case *dst.TypeSpec: - s.formatExpr(sp.Type, false, false) - default: - // noop - } -} - -// isGenerated checks whether the provided file bytes are from a generated file. -// This is done by looking for a set of typically-used strings in the first 5 lines. -func (s *Shortener) isGenerated(contents []byte) bool { - scanner := bufio.NewScanner(bytes.NewBuffer(contents)) - - for i := 0; scanner.Scan(); i++ { - if i >= 5 { - return false - } - - for _, term := range generatedTerms { - if strings.Contains(strings.ToLower(scanner.Text()), term) { - return true - } - } - } - - return false -} - -// chainLength determines the length of the function call chain in an expression. -func (s *Shortener) chainLength(callExpr *dst.CallExpr) int { - numCalls := 1 - currCall := callExpr - - for { - selectorExpr, ok := currCall.Fun.(*dst.SelectorExpr) - if !ok { - break - } - currCall, ok = selectorExpr.X.(*dst.CallExpr) - if !ok { - break - } - numCalls++ - } - - return numCalls -} diff --git a/tools/vendor/github.com/ldez/structtags/LICENSE b/tools/vendor/github.com/ldez/structtags/LICENSE new file mode 100644 index 000000000..f288702d2 --- /dev/null +++ b/tools/vendor/github.com/ldez/structtags/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/tools/vendor/github.com/ldez/structtags/parser/tag.go b/tools/vendor/github.com/ldez/structtags/parser/tag.go new file mode 100644 index 000000000..da9a97f67 --- /dev/null +++ b/tools/vendor/github.com/ldez/structtags/parser/tag.go @@ -0,0 +1,115 @@ +// Copyright 2009 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 parser + +import ( + "fmt" + "strconv" +) + +// Filler is the interface implemented by types that can fill elements from a struct tag. +type Filler[T any] interface { + // Data returns the [T] filled by the struct tag content. + Data() T + + // Fill fills the data from a struct tag. + Fill(key, value string) error +} + +// Tag parses a struct tag. +// +// Based on https://github.com/golang/go/blob/411c250d64304033181c46413a6e9381e8fe9b82/src/reflect/type.go#L1030-L1108 +// +//nolint:gocyclo +func Tag[T any](tag string, filler Filler[T]) (T, error) { + base := tag + + for tag != "" { + // Skip leading space. + i := 0 + for i < len(tag) && tag[i] == ' ' { + i++ + } + + tag = tag[i:] + if tag == "" { + break + } + + // Scan to colon. A space, a quote or a control character is a syntax error. + // Strictly speaking, control chars include the range [0x7f, 0x9f], not just + // [0x00, 0x1f], but in practice, we ignore the multi-byte control characters + // as it is simpler to inspect the tag's bytes than the tag's runes. + i = 0 + for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f { + i++ + } + + switch { + case i == 0: + var zero T + + return zero, fmt.Errorf("invalid struct tag syntax `%s`", base) + + case i+1 > len(tag): + var zero T + + return zero, fmt.Errorf("invalid struct tag syntax `%s`: missing `:`", base) + + case i+1 == len(tag): + var zero T + + return zero, fmt.Errorf("invalid struct tag value `%s`", base) + + case tag[i] != ':': + var zero T + + return zero, fmt.Errorf("invalid struct tag syntax `%s`: missing `:`", base) + + case tag[i+1] != '"': + var zero T + + return zero, fmt.Errorf("invalid struct tag value `%s`: missing opening quote", base) + } + + name := tag[:i] + tag = tag[i+1:] + + // Scan quoted string to find value. + i = 1 + for i < len(tag) && tag[i] != '"' { + if tag[i] == '\\' { + i++ + } + + i++ + } + + if i >= len(tag) { + var zero T + + return zero, fmt.Errorf("invalid struct tag value `%s`: missing closing quote", base) + } + + qvalue := tag[:i+1] + tag = tag[i+1:] + + value, err := strconv.Unquote(qvalue) + if err != nil { + var zero T + + return zero, fmt.Errorf("invalid struct tag value `%s`: %w", base, err) + } + + err = filler.Fill(name, value) + if err != nil { + var zero T + + return zero, err + } + } + + return filler.Data(), nil +} diff --git a/tools/vendor/github.com/ldez/structtags/parser/value.go b/tools/vendor/github.com/ldez/structtags/parser/value.go new file mode 100644 index 000000000..cea0cfa81 --- /dev/null +++ b/tools/vendor/github.com/ldez/structtags/parser/value.go @@ -0,0 +1,83 @@ +package parser + +import "fmt" + +// Value parses a tag value. +// The value is split on comma, and escaped commas are ignored. +func Value(raw string, escapeComma bool) ([]string, error) { + if raw == "" { + return []string{""}, nil + } + + var values []string + + for raw != "" { + i := indexEscaped(raw, 0, escapeComma) + + if i == 0 { + values = append(values, "") + raw = raw[i+1:] + + if raw == "" { + values = append(values, "") + + break + } + + continue + } + + if i == len(raw) { + values = append(values, raw[:i]) + + break + } + + if i > len(raw) { + return nil, fmt.Errorf("syntax error in struct tag value %q", raw) + } + + value := raw[:i] + + endComma := raw[i] == ',' && raw[i+1:] == "" + + raw = raw[i+1:] + + values = append(values, value) + + if endComma { + values = append(values, "") + } + } + + return values, nil +} + +func indexEscaped(raw string, i int, escapeComma bool) int { + for i < len(raw) && raw[i] != ',' { + i++ + } + + if !escapeComma { + return i + } + + if i-1 >= 0 && raw[i-1] == '\\' { + j := i - 1 + + count := 1 + + for j >= 0 && raw[j] == '\\' { + count++ + j-- + } + + if count%2 == 0 { + i++ + + return indexEscaped(raw, i, escapeComma) + } + } + + return i +} diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/Makefile b/tools/vendor/github.com/nunnatsa/ginkgolinter/Makefile index 647ca1683..749ce0fe1 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/Makefile +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/Makefile @@ -34,3 +34,9 @@ test: unit-test test-cli goimports: go install golang.org/x/tools/cmd/goimports@latest goimports -w -local="github.com/nunnatsa/ginkgolinter" $(shell find . -type f -name '*.go' ! -path "*/vendor/*") + +build-txtar-updater: + go build -o bin/ ./tools/txtar_updater + +update-txtar: build-txtar-updater + bin/txtar_updater --target-dir="./tests/testdata" --source-dir="./testdata/src/a" diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actual.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actual.go index 5bd6dd6e7..b3359f2a6 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actual.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actual.go @@ -7,7 +7,6 @@ import ( "golang.org/x/tools/go/analysis" "github.com/nunnatsa/ginkgolinter/internal/gomegahandler" - "github.com/nunnatsa/ginkgolinter/internal/gomegainfo" ) type Actual struct { @@ -21,13 +20,13 @@ type Actual struct { actualOffset int } -func New(origExpr, cloneExpr *ast.CallExpr, orig *ast.CallExpr, clone *ast.CallExpr, pass *analysis.Pass, timePkg string, info *gomegahandler.GomegaBasicInfo) (*Actual, bool) { - arg, actualOffset := getActualArgPayload(orig, clone, pass, info) +func New(origExpr, cloneExpr *ast.CallExpr, clone *ast.CallExpr, pass *analysis.Pass, timePkg string, info *gomegahandler.GomegaBasicInfo) (*Actual, bool) { + arg, actualOffset := getActualArgPayload(clone, pass, info) if arg == nil { return nil, false } - argType := pass.TypesInfo.TypeOf(orig.Args[actualOffset]) + argType := pass.TypesInfo.TypeOf(info.RootCall.Args[actualOffset]) isTuple := false if tpl, ok := argType.(*gotypes.Tuple); ok { @@ -40,15 +39,15 @@ func New(origExpr, cloneExpr *ast.CallExpr, orig *ast.CallExpr, clone *ast.CallE isTuple = tpl.Len() > 1 } - isAsyncExpr := gomegainfo.IsAsyncActualMethod(info.MethodName) + isAsyncExpr := info.RootCallType == gomegahandler.AsyncAssertionCall var asyncArg *AsyncArg if isAsyncExpr { - asyncArg = newAsyncArg(origExpr, cloneExpr, orig, clone, argType, pass, actualOffset, timePkg) + asyncArg = newAsyncArg(origExpr, cloneExpr, info.RootCall, clone, argType, pass, actualOffset, timePkg) } return &Actual{ - Orig: orig, + Orig: info.RootCall, Clone: clone, Arg: arg, argType: argType, diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actualarg.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actualarg.go index 05f640cc0..39341b1f8 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actualarg.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/actual/actualarg.go @@ -42,8 +42,8 @@ func (a ArgType) Is(val ArgType) bool { return a&val != 0 } -func getActualArgPayload(origActualExpr, actualExprClone *ast.CallExpr, pass *analysis.Pass, info *gomegahandler.GomegaBasicInfo) (ArgPayload, int) { - origArgExpr, argExprClone, actualOffset, isGomegaExpr := getActualArg(origActualExpr, actualExprClone, info.MethodName, pass) +func getActualArgPayload(actualExprClone *ast.CallExpr, pass *analysis.Pass, info *gomegahandler.GomegaBasicInfo) (ArgPayload, int) { + origArgExpr, argExprClone, actualOffset, isGomegaExpr := getActualArg(actualExprClone, info, pass) if !isGomegaExpr { return nil, 0 } @@ -79,13 +79,14 @@ func getActualArgPayload(origActualExpr, actualExprClone *ast.CallExpr, pass *an return newRegularArgPayload(origArgExpr, argExprClone, pass), actualOffset } -func getActualArg(origActualExpr *ast.CallExpr, actualExprClone *ast.CallExpr, actualMethodName string, pass *analysis.Pass) (ast.Expr, ast.Expr, int, bool) { +func getActualArg(actualExprClone *ast.CallExpr, info *gomegahandler.GomegaBasicInfo, pass *analysis.Pass) (ast.Expr, ast.Expr, int, bool) { var ( - origArgExpr ast.Expr - argExprClone ast.Expr + origArgExpr ast.Expr + argExprClone ast.Expr + origActualExpr = info.RootCall ) - funcOffset := gomegainfo.ActualArgOffset(actualMethodName) + funcOffset := gomegainfo.ActualArgOffset(info.MethodName) if funcOffset < 0 { return nil, nil, 0, false } @@ -97,7 +98,7 @@ func getActualArg(origActualExpr *ast.CallExpr, actualExprClone *ast.CallExpr, a origArgExpr = origActualExpr.Args[funcOffset] argExprClone = actualExprClone.Args[funcOffset] - if gomegainfo.IsAsyncActualMethod(actualMethodName) { + if info.RootCallType == gomegahandler.AsyncAssertionCall { if ginkgoinfo.IsGinkgoContext(pass.TypesInfo.TypeOf(origArgExpr)) { funcOffset++ if len(origActualExpr.Args) <= funcOffset { diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/expression.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/expression.go index 1909207e2..133c84e2a 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/expression.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/expression.go @@ -27,19 +27,26 @@ type GomegaExpression struct { origAssertionFuncName string actualFuncName string - isAsync bool - isUsingGomegaVar bool + isAsync bool actual *actual.Actual matcher *matcher.Matcher - handler gomegahandler.Handler + handler *gomegahandler.Handler } -func New(origExpr *ast.CallExpr, pass *analysis.Pass, handler gomegahandler.Handler, timePkg string) (*GomegaExpression, bool) { - info, ok := handler.GetGomegaBasicInfo(origExpr) - if !ok || !gomegainfo.IsActualMethod(info.MethodName) { - return nil, false +func New(origExpr *ast.CallExpr, pass *analysis.Pass, handler *gomegahandler.Handler, timePkg string) (gexp *GomegaExpression) { + info := handler.GetGomegaBasicInfo(origExpr) + if info == nil { + return nil + } + + switch info.RootCallType { + case gomegahandler.AsyncAssertionCall, gomegahandler.SyncAssertionCall: + // Okay, that's what we want here. + default: + // Cannot handle anything else. + return nil } origSel, ok := origExpr.Fun.(*ast.SelectorExpr) @@ -47,42 +54,42 @@ func New(origExpr *ast.CallExpr, pass *analysis.Pass, handler gomegahandler.Hand return &GomegaExpression{ orig: origExpr, actualFuncName: info.MethodName, - }, true + } } exprClone := astcopy.CallExpr(origExpr) selClone := exprClone.Fun.(*ast.SelectorExpr) - origActual := handler.GetActualExpr(origSel) + origActual := info.RootCall if origActual == nil { - return nil, false + return nil } - actualClone := handler.GetActualExprClone(origSel, selClone) + actualClone := handler.GetActualExprClone(origActual, origSel, selClone) if actualClone == nil { - return nil, false + return nil } - actl, ok := actual.New(origExpr, exprClone, origActual, actualClone, pass, timePkg, info) + actl, ok := actual.New(origExpr, exprClone, actualClone, pass, timePkg, info) if !ok { - return nil, false + return nil } origMatcher, ok := origExpr.Args[0].(*ast.CallExpr) if !ok { - return nil, false + return nil } matcherClone := exprClone.Args[0].(*ast.CallExpr) - mtchr, ok := matcher.New(origMatcher, matcherClone, pass, handler) - if !ok { - return nil, false + mtchr := matcher.New(origMatcher, matcherClone, pass, handler) + if mtchr == nil { + return nil } exprClone.Args[0] = mtchr.Clone - gexp := &GomegaExpression{ + gexp = &GomegaExpression{ orig: origExpr, clone: exprClone, @@ -90,8 +97,7 @@ func New(origExpr *ast.CallExpr, pass *analysis.Pass, handler gomegahandler.Hand origAssertionFuncName: origSel.Sel.Name, actualFuncName: info.MethodName, - isAsync: actl.IsAsync(), - isUsingGomegaVar: info.UseGomegaVar, + isAsync: actl.IsAsync(), actual: actl, matcher: mtchr, @@ -103,7 +109,7 @@ func New(origExpr *ast.CallExpr, pass *analysis.Pass, handler gomegahandler.Hand gexp.ReverseAssertionFuncLogic() } - return gexp, true + return gexp } func (e *GomegaExpression) IsMissingAssertion() bool { @@ -135,10 +141,6 @@ func (e *GomegaExpression) IsAsync() bool { return e.isAsync } -func (e *GomegaExpression) IsUsingGomegaVar() bool { - return e.isUsingGomegaVar -} - func (e *GomegaExpression) ReverseAssertionFuncLogic() { assertionFunc := e.clone.Fun.(*ast.SelectorExpr).Sel newName := reverseassertion.ChangeAssertionLogic(assertionFunc.Name) diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcher.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcher.go index 0636278e2..208437a5d 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcher.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcher.go @@ -34,19 +34,19 @@ type Matcher struct { Clone *ast.CallExpr info Info reverseLogic bool - handler gomegahandler.Handler + handler *gomegahandler.Handler hasNotMatcher bool // true if the matcher is wrapped with a "Not" matcher } -func New(origMatcher, matcherClone *ast.CallExpr, pass *analysis.Pass, handler gomegahandler.Handler) (*Matcher, bool) { +func New(origMatcher, matcherClone *ast.CallExpr, pass *analysis.Pass, handler *gomegahandler.Handler) *Matcher { reverse := false hasNotMatcher := false var assertFuncName string for { - info, ok := handler.GetGomegaBasicInfo(origMatcher) - if !ok { - return nil, false + info := handler.GetGomegaBasicInfo(origMatcher) + if info == nil { + return nil } if info.MethodName != "Not" { @@ -56,9 +56,10 @@ func New(origMatcher, matcherClone *ast.CallExpr, pass *analysis.Pass, handler g hasNotMatcher = true reverse = !reverse + var ok bool origMatcher, ok = origMatcher.Args[0].(*ast.CallExpr) if !ok { - return nil, false + return nil } matcherClone = matcherClone.Args[0].(*ast.CallExpr) } @@ -71,7 +72,7 @@ func New(origMatcher, matcherClone *ast.CallExpr, pass *analysis.Pass, handler g reverseLogic: reverse, hasNotMatcher: hasNotMatcher, handler: handler, - }, true + } } func (m *Matcher) ShouldReverseLogic() bool { diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcherinfo.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcherinfo.go index de15526ec..612209998 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcherinfo.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcherinfo.go @@ -53,7 +53,7 @@ type Info interface { MatcherName() string } -func getMatcherInfo(orig, clone *ast.CallExpr, matcherName string, pass *analysis.Pass, handler gomegahandler.Handler) Info { +func getMatcherInfo(orig, clone *ast.CallExpr, matcherName string, pass *analysis.Pass, handler *gomegahandler.Handler) Info { switch matcherName { case equal: return newEqualMatcher(orig.Args[0], clone.Args[0], pass) @@ -97,14 +97,14 @@ func getMatcherInfo(orig, clone *ast.CallExpr, matcherName string, pass *analysi return newMatchErrorMatcher(orig.Args, pass) case haveValue: - if nestedMatcher, ok := getNestedMatcher(orig, clone, 0, pass, handler); ok { + if nestedMatcher := getNestedMatcher(orig, clone, 0, pass, handler); nestedMatcher != nil { return &HaveValueMatcher{ nested: nestedMatcher, } } case withTransform: - if nestedMatcher, ok := getNestedMatcher(orig, clone, 1, pass, handler); ok { + if nestedMatcher := getNestedMatcher(orig, clone, 1, pass, handler); nestedMatcher != nil { return newWithTransformMatcher(orig.Args[0], nestedMatcher, pass) } @@ -116,7 +116,7 @@ func getMatcherInfo(orig, clone *ast.CallExpr, matcherName string, pass *analysi matcherType |= AndMatherType } - if m, ok := newMultipleMatchersMatcher(matcherType, orig.Args, clone.Args, pass, handler); ok { + if m := newMultipleMatchersMatcher(matcherType, orig.Args, clone.Args, pass, handler); m != nil { return m } diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcherwithnest.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcherwithnest.go index cc26e5ac2..7511bd28a 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcherwithnest.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/matcherwithnest.go @@ -44,14 +44,14 @@ func (m *WithTransformMatcher) GetFuncType() gotypes.Type { return m.funcType } -func getNestedMatcher(orig, clone *ast.CallExpr, offset int, pass *analysis.Pass, handler gomegahandler.Handler) (*Matcher, bool) { +func getNestedMatcher(orig, clone *ast.CallExpr, offset int, pass *analysis.Pass, handler *gomegahandler.Handler) *Matcher { if origNested, ok := orig.Args[offset].(*ast.CallExpr); ok { cloneNested := clone.Args[offset].(*ast.CallExpr) return New(origNested, cloneNested, pass, handler) } - return nil, false + return nil } func newWithTransformMatcher(fun ast.Expr, nested *Matcher, pass *analysis.Pass) *WithTransformMatcher { diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/multiplematchers.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/multiplematchers.go index 9ce0cf5b8..184d0302b 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/multiplematchers.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/expression/matcher/multiplematchers.go @@ -24,18 +24,18 @@ func (m *MultipleMatchersMatcher) MatcherName() string { return and } -func newMultipleMatchersMatcher(matherType Type, orig, clone []ast.Expr, pass *analysis.Pass, handler gomegahandler.Handler) (*MultipleMatchersMatcher, bool) { +func newMultipleMatchersMatcher(matherType Type, orig, clone []ast.Expr, pass *analysis.Pass, handler *gomegahandler.Handler) *MultipleMatchersMatcher { matchers := make([]*Matcher, len(orig)) for i := range orig { nestedOrig, ok := orig[i].(*ast.CallExpr) if !ok { - return nil, false + return nil } - m, ok := New(nestedOrig, clone[i].(*ast.CallExpr), pass, handler) - if !ok { - return nil, false + m := New(nestedOrig, clone[i].(*ast.CallExpr), pass, handler) + if m == nil { + return nil } m.reverseLogic = false @@ -46,7 +46,7 @@ func newMultipleMatchersMatcher(matherType Type, orig, clone []ast.Expr, pass *a return &MultipleMatchersMatcher{ matherType: matherType, matchers: matchers, - }, true + } } func (m *MultipleMatchersMatcher) Len() int { diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/dothandler.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/dothandler.go deleted file mode 100644 index 8ab87c76e..000000000 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/dothandler.go +++ /dev/null @@ -1,109 +0,0 @@ -package gomegahandler - -import ( - "go/ast" - - "golang.org/x/tools/go/analysis" - - "github.com/nunnatsa/ginkgolinter/internal/gomegainfo" -) - -// dotHandler is used when importing gomega with dot; i.e. -// import . "github.com/onsi/gomega" -type dotHandler struct { - pass *analysis.Pass -} - -// GetGomegaBasicInfo returns the name of the gomega function, e.g. `Expect` + some additional info -func (h dotHandler) GetGomegaBasicInfo(expr *ast.CallExpr) (*GomegaBasicInfo, bool) { - info := &GomegaBasicInfo{} - for { - switch actualFunc := expr.Fun.(type) { - case *ast.Ident: - info.MethodName = actualFunc.Name - return info, true - case *ast.SelectorExpr: - if h.isGomegaVar(actualFunc.X) { - info.UseGomegaVar = true - info.MethodName = actualFunc.Sel.Name - return info, true - } - - if actualFunc.Sel.Name == "Error" { - info.HasErrorMethod = true - } - - if x, ok := actualFunc.X.(*ast.CallExpr); ok { - expr = x - } else { - return nil, false - } - default: - return nil, false - } - } -} - -// ReplaceFunction replaces the function with another one, for fix suggestions -func (dotHandler) ReplaceFunction(caller *ast.CallExpr, newExpr *ast.Ident) { - switch f := caller.Fun.(type) { - case *ast.Ident: - caller.Fun = newExpr - case *ast.SelectorExpr: - f.Sel = newExpr - } -} - -func (dotHandler) GetNewWrapperMatcher(name string, existing *ast.CallExpr) *ast.CallExpr { - return &ast.CallExpr{ - Fun: ast.NewIdent(name), - Args: []ast.Expr{existing}, - } -} - -func (h dotHandler) GetActualExpr(assertionFunc *ast.SelectorExpr) *ast.CallExpr { - actualExpr, ok := assertionFunc.X.(*ast.CallExpr) - if !ok { - return nil - } - - switch fun := actualExpr.Fun.(type) { - case *ast.Ident: - return actualExpr - case *ast.SelectorExpr: - if gomegainfo.IsActualMethod(fun.Sel.Name) { - if h.isGomegaVar(fun.X) { - return actualExpr - } - } else { - return h.GetActualExpr(fun) - } - } - return nil -} - -func (h dotHandler) GetActualExprClone(origFunc, funcClone *ast.SelectorExpr) *ast.CallExpr { - actualExpr, ok := funcClone.X.(*ast.CallExpr) - if !ok { - return nil - } - - switch funClone := actualExpr.Fun.(type) { - case *ast.Ident: - return actualExpr - case *ast.SelectorExpr: - origFun := origFunc.X.(*ast.CallExpr).Fun.(*ast.SelectorExpr) - if gomegainfo.IsActualMethod(funClone.Sel.Name) { - if h.isGomegaVar(origFun.X) { - return actualExpr - } - } else { - return h.GetActualExprClone(origFun, funClone) - } - } - return nil -} - -func (h dotHandler) isGomegaVar(x ast.Expr) bool { - return gomegainfo.IsGomegaVar(x, h.pass) -} diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/handler.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/handler.go index 9eb8ce1dd..1705104cc 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/handler.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/handler.go @@ -2,6 +2,8 @@ package gomegahandler import ( "go/ast" + gotypes "go/types" + "strings" "golang.org/x/tools/go/analysis" ) @@ -10,45 +12,269 @@ const ( importPath = `"github.com/onsi/gomega"` ) -// Handler provide different handling, depend on the way gomega was imported, whether -// in imported with "." name, custom name or without any name. -type Handler interface { - // GetActualFuncName returns the name of the gomega function, e.g. `Expect` - GetGomegaBasicInfo(*ast.CallExpr) (*GomegaBasicInfo, bool) - // ReplaceFunction replaces the function with another one, for fix suggestions - ReplaceFunction(*ast.CallExpr, *ast.Ident) - - GetActualExpr(assertionFunc *ast.SelectorExpr) *ast.CallExpr +// GomegaBasicInfo is the result of [Handler.GetGomegaBasicInfo]. +type GomegaBasicInfo struct { + // MethodName is the top-level Gomega method in which an expression is rooted (e.g. Expect). + // Empty is unknown. + MethodName string + // True if the expression includes an Error call. + HasErrorMethod bool - GetActualExprClone(origFunc, funcClone *ast.SelectorExpr) *ast.CallExpr + // RootCall is the call which is root of the expression that GetGomegaBasicInfo + // was called for. + // + // This is either the function which is passed the actual value (see IsAssertion + // and IsAsyncAssertion) or a function which is passed some expected value (see + // IsMatcher). + RootCall *ast.CallExpr - GetNewWrapperMatcher(name string, existing *ast.CallExpr) *ast.CallExpr + // Type determines what kind of Gomega function is called. + RootCallType CallType } -type GomegaBasicInfo struct { - MethodName string - UseGomegaVar bool - HasErrorMethod bool -} +// CallType determines what kind of function call is described by [GomegaBasicInfo]. +type CallType int + +const ( + // OtherCall is the unspecified type. [GetGomegaBasicInfo] never returns a GomegaBasicInfo + // with this type. + OtherCall CallType = iota + // SyncAssertionCall returns gtypes.Assertion. + SyncAssertionCall + // AsyncAssertionCall returns gtypes.AsyncAssertion. + AsyncAssertionCall + // MatcherCall returns gtypes.GomegaMatcher. + MatcherCall +) // GetGomegaHandler returns a gomegar handler according to the way gomega was imported in the specific file -func GetGomegaHandler(file *ast.File, pass *analysis.Pass) Handler { +func GetGomegaHandler(file *ast.File, pass *analysis.Pass) *Handler { + // Look up the Gomega types package. It might be imported directly or indirectly. + gtypesPkg := getPackage(pass.Pkg, "github.com/onsi/gomega/types") + if gtypesPkg == nil { + return nil // No gomega import: this file does not use gomega, neither directly nor indirectly. + } + + // Look up the interfaces. They may be nil if not in use. + assertionInterface := lookupInterface(gtypesPkg, "Assertion") + asyncAssertionInterface := lookupInterface(gtypesPkg, "AsyncAssertion") + matcherInterface := lookupInterface(gtypesPkg, "GomegaMatcher") + + // If there is a direct import, then this gets replaced. + // + // Otherwise gomega might be used indirectly, in which case + // we have to make an educated guess what the package name + // should be when suggesting fixes. + // + // Let's assume that users would want named importing, + // because that is the recommended approach in Go. + // + // In practice it doesn't really matter because the only failure + // can be a generic "missing assertion", which doesn't + // reference a gomega method. + name := "gomega" for _, imp := range file.Imports { if imp.Path.Value != importPath { continue } - switch name := imp.Name.String(); name { + switch n := imp.Name.String(); n { case ".": - return &dotHandler{ - pass: pass, - } - case "": // import with no local name - return &nameHandler{name: "gomega", pass: pass} + name = "" + case "": // import with no local name, default is good default: - return &nameHandler{name: name, pass: pass} + name = n + } + } + + return &Handler{ + name: name, + pass: pass, + syncAssertionInterface: assertionInterface, + asyncAssertionInterface: asyncAssertionInterface, + matcherInterface: matcherInterface, + } +} + +// getPackage searches recursively for a specific package, identified by it's full import name. +// +// Surprisingly, the imports may contain cycles (unsafe.unsafe -> ... internal/runtime/sys.sys ... -> unsafe.unsafe), +// so we have to detect those. We also don't want to check the same package more than once. +func getPackage(pkg *gotypes.Package, importName string) *gotypes.Package { + return getPackageRecursively(pkg, importName, make(map[*gotypes.Package]bool)) +} + +func getPackageRecursively(pkg *gotypes.Package, importName string, seen map[*gotypes.Package]bool) *gotypes.Package { + if seen[pkg] { + // Prevent recursion, don't check again. + return nil + } + seen[pkg] = true + + // In unit testing, the actual path is a/vendor/github.com/onsi/gomega/types, so we have to relax + // the check a bit. + if strings.HasSuffix(pkg.Path(), importName) { + return pkg + } + for _, pkg := range pkg.Imports() { + if pkg := getPackageRecursively(pkg, importName, seen); pkg != nil { + return pkg } } + return nil +} + +func lookupInterface(pkg *gotypes.Package, name string) *gotypes.Interface { + def := pkg.Scope().Lookup(name) + if def == nil { + return nil + } + if i, ok := def.Type().Underlying().(*gotypes.Interface); ok { + return i + } + return nil +} + +// Handler provide different handling, depend on the way gomega was imported, whether +// in imported with "." name, custom name or without any name. +type Handler struct { + // name is the name under which the gomega package was imported, empty if a dot import + name string + pass *analysis.Pass + + syncAssertionInterface, asyncAssertionInterface, matcherInterface *gotypes.Interface +} - return nil // no gomega import; this file does not use gomega +// GetGomegaBasicInfo returns the name of the gomega function, e.g. `Expect` + some additional info. +// +// We identify gomega functions as: +// - The result implements a gomega interface (Assertion/AsyncAssertion/GomegaMatcher). +// - It's not a method called on such an interface. +// +// The type of the result doesn't matter, it could be interface type itself, +// type alias, struct embedding gtypes.Assertion, some other type entirely, +// etc.): if it walks like a duck, quacks like a duck, it's a duck... +// +// The method name is picked up from the identifier (dot import) or from the selector (gomega.Expect, gomega.NewWithT(t).Expect). +// Returns nil if the root call cannot be determined or does not produce one of the Gomega interfaces. +func (g *Handler) GetGomegaBasicInfo(expr *ast.CallExpr) (info *GomegaBasicInfo) { + hasErrorMethod := false + for { + // Dive deeper? + if actualFunc, ok := expr.Fun.(*ast.SelectorExpr); ok && (g.implements(actualFunc.X, g.syncAssertionInterface) || g.implements(actualFunc.X, g.asyncAssertionInterface) || g.implements(actualFunc.X, g.matcherInterface)) { + x, ok := actualFunc.X.(*ast.CallExpr) + if !ok { + // Could be a variable. + // We need to have an actual function call at the root + // for parameter checking. We don't have one, so give up. + return nil + } + if actualFunc.Sel.Name == "Error" { + hasErrorMethod = true + } + + // Because actualFunc.X already implemented some gomega interface, + // actualFunc.Sel must be something like "WithOffset". + // It's not the root, so we have to keep looking. + expr = x + continue + } + + if callType := g.callType(expr); callType != OtherCall { + // Cannot dive deeper and it returns one of the unique + // Gomega interfaces, so this must be our root. + info := &GomegaBasicInfo{ + HasErrorMethod: hasErrorMethod, + RootCall: expr, + RootCallType: callType, + } + switch actualFunc := expr.Fun.(type) { + case *ast.Ident: + info.MethodName = actualFunc.Name + case *ast.SelectorExpr: + info.MethodName = actualFunc.Sel.Name + } + return info + } + + // Give up. + return nil + } +} + +// ReplaceFunction replaces the function with another one, for fix suggestions +func (g *Handler) ReplaceFunction(caller *ast.CallExpr, newExpr *ast.Ident) { + switch f := caller.Fun.(type) { + case *ast.Ident: + caller.Fun = newExpr + case *ast.SelectorExpr: + f.Sel = newExpr + } +} + +func (g *Handler) GetNewWrapperMatcher(name string, existing *ast.CallExpr) *ast.CallExpr { + if g.name == "" { + return &ast.CallExpr{ + Fun: ast.NewIdent(name), + Args: []ast.Expr{existing}, + } + } + + return &ast.CallExpr{ + Fun: &ast.SelectorExpr{ + X: ast.NewIdent(g.name), + Sel: ast.NewIdent(name), + }, + Args: []ast.Expr{existing}, + } +} + +func (g *Handler) implements(expr ast.Expr, i *gotypes.Interface) bool { + if i == nil { + // Interface wasn't found -> not in use -> the expression cannot implement it. + return false + } + exprType, ok := g.pass.TypesInfo.Types[expr] + return ok && gotypes.Implements(exprType.Type, i) +} + +func (g *Handler) callType(expr ast.Expr) CallType { + switch { + case g.implements(expr, g.syncAssertionInterface): + return SyncAssertionCall + case g.implements(expr, g.asyncAssertionInterface): + return AsyncAssertionCall + case g.implements(expr, g.matcherInterface): + return MatcherCall + default: + return OtherCall + } +} + +// GetActualExprClone dives into origFunc and funcClone in lockstep until it hits +// origRootCall in origFunc, then returns the corresponding CallExpr in funcClone. +func (g *Handler) GetActualExprClone(origRootCall *ast.CallExpr, origFunc, cloneFunc *ast.SelectorExpr) (cloneRootCall *ast.CallExpr) { + cloneExpr, ok := cloneFunc.X.(*ast.CallExpr) + if !ok { + return nil + } + origExpr, ok := origFunc.X.(*ast.CallExpr) + if !ok { + return nil + } + + if origExpr == origRootCall { + // Found it! + return cloneExpr + } + + cloneInnerFunc, ok := cloneExpr.Fun.(*ast.SelectorExpr) + if !ok { + return nil + } + origInnerFunc, ok := origExpr.Fun.(*ast.SelectorExpr) + if !ok { + return nil + } + return g.GetActualExprClone(origRootCall, origInnerFunc, cloneInnerFunc) } diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/namedhandler.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/namedhandler.go deleted file mode 100644 index 87e0fc22e..000000000 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegahandler/namedhandler.go +++ /dev/null @@ -1,123 +0,0 @@ -package gomegahandler - -import ( - "go/ast" - - "github.com/nunnatsa/ginkgolinter/internal/gomegainfo" - - "golang.org/x/tools/go/analysis" -) - -// nameHandler is used when importing gomega without name; i.e. -// import "github.com/onsi/gomega" -// -// or with a custom name; e.g. -// import customname "github.com/onsi/gomega" -type nameHandler struct { - name string - pass *analysis.Pass -} - -// GetGomegaBasicInfo returns the name of the gomega function, e.g. `Expect` + some additional info -func (g nameHandler) GetGomegaBasicInfo(expr *ast.CallExpr) (*GomegaBasicInfo, bool) { - info := &GomegaBasicInfo{} - for { - selector, ok := expr.Fun.(*ast.SelectorExpr) - if !ok { - return nil, false - } - - if selector.Sel.Name == "Error" { - info.HasErrorMethod = true - } - - switch x := selector.X.(type) { - case *ast.Ident: - if x.Name != g.name { - if !g.isGomegaVar(x) { - return nil, false - } - info.UseGomegaVar = true - } - - info.MethodName = selector.Sel.Name - - return info, true - - case *ast.CallExpr: - expr = x - - default: - return nil, false - } - } -} - -// ReplaceFunction replaces the function with another one, for fix suggestions -func (nameHandler) ReplaceFunction(caller *ast.CallExpr, newExpr *ast.Ident) { - caller.Fun.(*ast.SelectorExpr).Sel = newExpr -} - -func (g nameHandler) isGomegaVar(x ast.Expr) bool { - return gomegainfo.IsGomegaVar(x, g.pass) -} - -func (g nameHandler) GetActualExpr(assertionFunc *ast.SelectorExpr) *ast.CallExpr { - actualExpr, ok := assertionFunc.X.(*ast.CallExpr) - if !ok { - return nil - } - - switch fun := actualExpr.Fun.(type) { - case *ast.Ident: - return actualExpr - case *ast.SelectorExpr: - if x, ok := fun.X.(*ast.Ident); ok && x.Name == g.name { - return actualExpr - } - if gomegainfo.IsActualMethod(fun.Sel.Name) { - if g.isGomegaVar(fun.X) { - return actualExpr - } - } else { - return g.GetActualExpr(fun) - } - } - return nil -} - -func (g nameHandler) GetActualExprClone(origFunc, funcClone *ast.SelectorExpr) *ast.CallExpr { - actualExpr, ok := funcClone.X.(*ast.CallExpr) - if !ok { - return nil - } - - switch funClone := actualExpr.Fun.(type) { - case *ast.Ident: - return actualExpr - case *ast.SelectorExpr: - if x, ok := funClone.X.(*ast.Ident); ok && x.Name == g.name { - return actualExpr - } - origFun := origFunc.X.(*ast.CallExpr).Fun.(*ast.SelectorExpr) - if gomegainfo.IsActualMethod(funClone.Sel.Name) { - if g.isGomegaVar(origFun.X) { - return actualExpr - } - } else { - return g.GetActualExprClone(origFun, funClone) - } - } - - return nil -} - -func (g nameHandler) GetNewWrapperMatcher(name string, existing *ast.CallExpr) *ast.CallExpr { - return &ast.CallExpr{ - Fun: &ast.SelectorExpr{ - X: ast.NewIdent(g.name), - Sel: ast.NewIdent(name), - }, - Args: []ast.Expr{existing}, - } -} diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegainfo/gomegainfo.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegainfo/gomegainfo.go index 93be55ec0..c773d055e 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegainfo/gomegainfo.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/gomegainfo/gomegainfo.go @@ -36,15 +36,11 @@ var funcOffsetMap = map[string]int{ consistentlyWithOffset: 1, } -func IsActualMethod(name string) bool { - _, found := funcOffsetMap[name] - return found -} - func ActualArgOffset(methodName string) int { funcOffset, ok := funcOffsetMap[methodName] if !ok { - return -1 + // Assume first argument for unknown methods. + return 0 } return funcOffset } @@ -61,22 +57,11 @@ func GetAllowedAssertionMethods(actualMethodName string) string { return `"Should()", "To()", "ShouldNot()", "ToNot()" or "NotTo()"` default: - return "" + // Unknown wrapper or missing method name, mention all options. + return `one of "To/NotTo/ToNot" (for Expect assertions) or "Should/ShouldNot" (for Eventually/Consistently assertions)` } } -var asyncFuncSet = map[string]struct{}{ - eventually: {}, - eventuallyWithOffset: {}, - consistently: {}, - consistentlyWithOffset: {}, -} - -func IsAsyncActualMethod(name string) bool { - _, ok := asyncFuncSet[name] - return ok -} - func IsAssertionFunc(name string) bool { switch name { case to, toNot, notTo, should, shouldNot: diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/intervals/intervals.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/intervals/intervals.go index 51d55166d..868fb83ad 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/intervals/intervals.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/intervals/intervals.go @@ -5,6 +5,7 @@ import ( "go/constant" "go/token" gotypes "go/types" + "strconv" "time" "golang.org/x/tools/go/analysis" @@ -33,11 +34,12 @@ func GetDuration(pass *analysis.Pass, argOffset int, origInterval, intervalClone if basic.Info()&gotypes.IsInteger != 0 { if num, ok := constant.Int64Val(tv.Value); ok { return &NumericDurationValue{ - timePkg: timePkg, - numSeconds: num, - offset: argOffset, - dur: time.Duration(num) * time.Second, - expr: intervalClone, + timePkg: timePkg, + numSeconds: num, + offset: argOffset, + dur: time.Duration(num) * time.Second, + expr: intervalClone, + useOrigExpr: tv.Type.String() == "int", } } } @@ -45,14 +47,33 @@ func GetDuration(pass *analysis.Pass, argOffset int, origInterval, intervalClone if basic.Info()&gotypes.IsFloat != 0 { if num, ok := constant.Float64Val(tv.Value); ok { return &NumericDurationValue{ - timePkg: timePkg, - numSeconds: int64(num), - offset: argOffset, - dur: time.Duration(num) * time.Second, - expr: intervalClone, + timePkg: timePkg, + numSeconds: int64(num), + offset: argOffset, + dur: time.Duration(num) * time.Second, + expr: intervalClone, + useOrigExpr: false, } } } + + if basic.Info()&gotypes.IsString != 0 { + val, err := strconv.Unquote(tv.Value.ExactString()) + if err != nil { + val = tv.Value.String() + } + duration, err := time.ParseDuration(val) + if err != nil { + return &UnknownDurationValue{expr: intervalClone} + } + + return &StringDurationValue{ + timePkg: timePkg, + dur: duration, + expr: intervalClone, + offset: argOffset, + } + } } return &UnknownDurationValue{expr: intervalClone} @@ -90,11 +111,12 @@ func (r RealDurationValue) Duration() time.Duration { } type NumericDurationValue struct { - timePkg string - numSeconds int64 - offset int - dur time.Duration - expr ast.Expr + timePkg string + numSeconds int64 + offset int + dur time.Duration + expr ast.Expr + useOrigExpr bool } func (r *NumericDurationValue) Duration() time.Duration { @@ -107,9 +129,13 @@ func (r *NumericDurationValue) GetOffset() int { func (r *NumericDurationValue) GetDurationExpr() ast.Expr { var newArg ast.Expr - second := &ast.SelectorExpr{ - Sel: ast.NewIdent("Second"), - X: ast.NewIdent(r.timePkg), + second := getUnit(r.timePkg, "Second") + + var y ast.Expr + if r.useOrigExpr { + y = r.expr + } else { + y = &ast.BasicLit{Value: strconv.Itoa(int(r.numSeconds)), Kind: token.INT} } if r.numSeconds == 1 { @@ -118,7 +144,7 @@ func (r *NumericDurationValue) GetDurationExpr() ast.Expr { newArg = &ast.BinaryExpr{ X: second, Op: token.MUL, - Y: r.expr, + Y: y, } } @@ -134,8 +160,9 @@ func (r UnknownDurationValue) Duration() time.Duration { } type UnknownNumericValue struct { - expr ast.Expr - offset int + expr ast.Expr + offset int + timePkg string } func (r UnknownNumericValue) Duration() time.Duration { @@ -144,10 +171,7 @@ func (r UnknownNumericValue) Duration() time.Duration { func (r UnknownNumericValue) GetDurationExpr() ast.Expr { return &ast.BinaryExpr{ - X: &ast.SelectorExpr{ - Sel: ast.NewIdent("Second"), - X: ast.NewIdent("time"), - }, + X: getUnit(r.timePkg, "Second"), Op: token.MUL, Y: r.expr, } @@ -164,3 +188,133 @@ type UnknownDurationTypeValue struct { func (r UnknownDurationTypeValue) Duration() time.Duration { return 0 } + +type StringDurationValue struct { + timePkg string + dur time.Duration + expr ast.Expr + offset int +} + +func (r StringDurationValue) Duration() time.Duration { + return r.dur +} + +func (r StringDurationValue) GetOffset() int { + return r.offset +} + +func (r StringDurationValue) GetDurationExpr() ast.Expr { + return durationToExpr(r.dur, r.timePkg) +} + +func durationToExpr(duration time.Duration, timePkg string) ast.Expr { + var durationExpr ast.Expr + + if duration >= time.Hour { + hours := duration / time.Hour + duration -= hours * time.Hour + durationExpr = getDurationExpression("Hour", timePkg, hours) + } + + if duration >= time.Minute { + minutes := duration / time.Minute + duration -= minutes * time.Minute + minExp := getDurationExpression("Minute", timePkg, minutes) + + if durationExpr == nil { + durationExpr = minExp + } else { + durationExpr = &ast.BinaryExpr{ + X: durationExpr, + Op: token.ADD, + Y: minExp, + } + } + } + + if duration >= time.Second { + seconds := duration / time.Second + duration -= seconds * time.Second + secExpr := getDurationExpression("Second", timePkg, seconds) + + if durationExpr == nil { + durationExpr = secExpr + } else { + durationExpr = &ast.BinaryExpr{ + X: durationExpr, + Op: token.ADD, + Y: secExpr, + } + } + } + + if duration >= time.Millisecond { + milliseconds := duration / time.Millisecond + duration -= milliseconds * time.Millisecond + millisecondsExpr := getDurationExpression("Millisecond", timePkg, milliseconds) + + if durationExpr == nil { + durationExpr = millisecondsExpr + } else { + durationExpr = &ast.BinaryExpr{ + X: durationExpr, + Op: token.ADD, + Y: millisecondsExpr, + } + } + } + + if duration >= time.Microsecond { + microseconds := duration / time.Microsecond + duration -= microseconds * time.Microsecond + microsecondsExpr := getDurationExpression("Microsecond", timePkg, microseconds) + + if durationExpr == nil { + durationExpr = microsecondsExpr + } else { + durationExpr = &ast.BinaryExpr{ + X: durationExpr, + Op: token.ADD, + Y: microsecondsExpr, + } + } + } + + if duration > 0 { + nanosecondsExpr := getDurationExpression("Nanosecond", timePkg, duration) + + if durationExpr == nil { + durationExpr = nanosecondsExpr + } else { + durationExpr = &ast.BinaryExpr{ + X: durationExpr, + Op: token.ADD, + Y: nanosecondsExpr, + } + } + } + + return durationExpr +} + +func getDurationExpression(unitName, timePkg string, amount time.Duration) ast.Expr { + unit := getUnit(timePkg, unitName) + + if amount == 1 { + return unit + } + + return &ast.BinaryExpr{ + X: unit, + Op: token.MUL, + Y: &ast.BasicLit{Value: strconv.FormatInt(int64(amount), 10), Kind: token.INT}, + } +} + +func getUnit(timePkg, unitName string) ast.Expr { + return &ast.SelectorExpr{ + X: ast.NewIdent(timePkg), + Sel: ast.NewIdent(unitName), + } +} diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/asynctimeintervalsrule.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/asynctimeintervalsrule.go index ffac8bc13..309f12aa7 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/asynctimeintervalsrule.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/asynctimeintervalsrule.go @@ -80,7 +80,7 @@ func checkInterval(gexp *expression.GomegaExpression, durVal intervals.DurationV switch to := durVal.(type) { case *intervals.RealDurationValue, *intervals.UnknownDurationTypeValue: - case *intervals.NumericDurationValue: + case *intervals.NumericDurationValue, *intervals.StringDurationValue: if checkNumericInterval(gexp.GetActualClone(), to) { reportBuilder.AddIssue(true, onlyUseTimeDurationForInterval) } diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/missingassertionrule.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/missingassertionrule.go index e96ac2902..8857d8f34 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/missingassertionrule.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/internal/rules/missingassertionrule.go @@ -9,12 +9,6 @@ import ( const missingAssertionMessage = `%q: missing assertion method. Expected %s` -type MissingAssertionRule struct{} - -func (r MissingAssertionRule) isApplied(gexp *expression.GomegaExpression) bool { - return gexp.IsMissingAssertion() -} - // MissingAssertionRule checks if the assertion method is missing. In this case, the test does not make any assertion. // This is mostly relevant for the async actual methods, that tend to be longer, and so harder to spot the missing assertion // by just reading the test code. @@ -32,6 +26,12 @@ func (r MissingAssertionRule) isApplied(gexp *expression.GomegaExpression) bool // Eventually(func() error { // return nil // }).Should(Succeed()) +type MissingAssertionRule struct{} + +func (r MissingAssertionRule) isApplied(gexp *expression.GomegaExpression) bool { + return gexp.IsMissingAssertion() +} + func (r MissingAssertionRule) Apply(gexp *expression.GomegaExpression, _ config.Config, reportBuilder *reports.Builder) bool { if !r.isApplied(gexp) { return false diff --git a/tools/vendor/github.com/nunnatsa/ginkgolinter/linter/ginkgo_linter.go b/tools/vendor/github.com/nunnatsa/ginkgolinter/linter/ginkgo_linter.go index fefb8d63e..338262e1a 100644 --- a/tools/vendor/github.com/nunnatsa/ginkgolinter/linter/ginkgo_linter.go +++ b/tools/vendor/github.com/nunnatsa/ginkgolinter/linter/ginkgo_linter.go @@ -41,7 +41,8 @@ func (l *GinkgoLinter) Run(pass *analysis.Pass) (any, error) { gomegaHndlr := gomegahandler.GetGomegaHandler(file, pass) ginkgoHndlr := ginkgohandler.GetGinkgoHandler(file) - if gomegaHndlr == nil && ginkgoHndlr == nil { // no gomega or ginkgo imports => no use in gomega in this file; nothing to do here + if gomegaHndlr == nil && ginkgoHndlr == nil { + // no gomega or ginkgo imports or dependencies => no use in gomega in this file; nothing to do here continue } @@ -86,8 +87,8 @@ func (l *GinkgoLinter) Run(pass *analysis.Pass) (any, error) { return true } - gexp, ok := expression.New(assertionExp, pass, gomegaHndlr, getTimePkg(file)) - if !ok || gexp == nil { + gexp := expression.New(assertionExp, pass, gomegaHndlr, getTimePkg(file)) + if gexp == nil { return true } diff --git a/tools/vendor/go.augendre.info/arangolint/pkg/analyzer/analyzer.go b/tools/vendor/go.augendre.info/arangolint/pkg/analyzer/analyzer.go index 53f19e2e6..6eebe4880 100644 --- a/tools/vendor/go.augendre.info/arangolint/pkg/analyzer/analyzer.go +++ b/tools/vendor/go.augendre.info/arangolint/pkg/analyzer/analyzer.go @@ -23,12 +23,19 @@ import ( ) const ( - allowImplicitFieldName = "AllowImplicit" - msgMissingAllowImplicit = "missing AllowImplicit option" - methodBeginTransaction = "BeginTransaction" - expectedBeginTxnArgs = 3 - arangoDatabaseTypeSuffix = "github.com/arangodb/go-driver/v2/arangodb.Database" - arangoPackageSuffix = "github.com/arangodb/go-driver/v2/arangodb" + allowImplicitFieldName = "AllowImplicit" + msgMissingAllowImplicit = "missing AllowImplicit option" + msgQueryConcatenation = "query string uses concatenation instead of bind variables" + methodBeginTransaction = "BeginTransaction" + methodQuery = "Query" + methodQueryBatch = "QueryBatch" + methodValidateQuery = "ValidateQuery" + methodExplainQuery = "ExplainQuery" + expectedBeginTxnArgs = 3 + arangoDatabaseTypeSuffix = "github.com/arangodb/go-driver/v2/arangodb.Database" + arangoTransactionTypeSuffix = "github.com/arangodb/go-driver/v2/arangodb.Transaction" + arangoPackageSuffix = "github.com/arangodb/go-driver/v2/arangodb" + fmtPackagePath = "fmt" ) var errInvalidAnalysis = errors.New("invalid analysis") @@ -59,6 +66,7 @@ func run(pass *analysis.Pass) (interface{}, error) { // node is guaranteed to be *ast.CallExpr due to the filter above. call := node.(*ast.CallExpr) //nolint:forcetypeassert handleBeginTransactionCall(call, pass, stack) + handleQueryCall(call, pass, stack) return true }) @@ -90,6 +98,124 @@ func handleBeginTransactionCall(call *ast.CallExpr, pass *analysis.Pass, stack [ } } +// handleQueryCall validates Query/QueryBatch/ValidateQuery/ExplainQuery call sites +// to detect AQL injection vulnerabilities via string concatenation. +func handleQueryCall(call *ast.CallExpr, pass *analysis.Pass, stack []ast.Node) { + methodName, queryArgIndex := identifyQueryMethod(call, pass) + if methodName == "" { + return + } + + // Ensure the call has enough arguments + if len(call.Args) <= queryArgIndex { + return + } + + queryArg := unwrapParens(call.Args[queryArgIndex]) + + if shouldReportQueryConcatenation(queryArg, pass, stack, call.Pos()) { + diag := analysis.Diagnostic{ + Pos: queryArg.Pos(), + Message: msgQueryConcatenation, + } + pass.Report(diag) + } +} + +// identifyQueryMethod checks if the call is to a Database or Transaction query method +// and returns the method name and the index of the query string argument. +// Returns empty string if not a query method. +func identifyQueryMethod( + call *ast.CallExpr, + pass *analysis.Pass, +) (methodName string, queryArgIndex int) { + selExpr, isSelector := call.Fun.(*ast.SelectorExpr) + if !isSelector || selExpr.Sel == nil { + return "", 0 + } + + methodName = selExpr.Sel.Name + + queryArgIndex = getQueryArgIndex(methodName) + if queryArgIndex == -1 { + return "", 0 + } + + // Verify it's called on a Database or Transaction type + xType := pass.TypesInfo.TypeOf(selExpr.X) + if xType == nil { + return "", 0 + } + + if isQueryReceiverType(xType, pass) { + return methodName, queryArgIndex + } + + return "", 0 +} + +// getQueryArgIndex returns the index of the query argument for a given method name, +// or -1 if the method is not a query method. +func getQueryArgIndex(methodName string) int { + switch methodName { + case methodQuery, methodQueryBatch, methodValidateQuery, methodExplainQuery: + return 1 + default: + return -1 + } +} + +// isQueryReceiverType checks if the given type is a Database or Transaction type. +func isQueryReceiverType(xType types.Type, pass *analysis.Pass) bool { + // Try to find the arangodb package and get Database and Transaction types + dbType, trxType := getArangoDBTypes(pass) + + if dbType != nil && types.AssignableTo(xType, dbType) { + return true + } + + if trxType != nil && types.AssignableTo(xType, trxType) { + return true + } + + // Fallback: direct receiver type match + receiverTypeStr := xType.String() + + return strings.HasSuffix(receiverTypeStr, arangoDatabaseTypeSuffix) || + strings.HasSuffix(receiverTypeStr, arangoTransactionTypeSuffix) +} + +// getArangoDBTypes retrieves the Database and Transaction types from the arangodb package. +func getArangoDBTypes(pass *analysis.Pass) (dbType, trxType types.Type) { + for _, imp := range pass.Pkg.Imports() { + if !strings.HasSuffix(imp.Path(), arangoPackageSuffix) { + continue + } + + dbType = lookupType(imp, "Database") + trxType = lookupType(imp, "Transaction") + + break + } + + return dbType, trxType +} + +// lookupType looks up a type by name in a package scope. +func lookupType(pkg *types.Package, name string) types.Type { + obj := pkg.Scope().Lookup(name) + if obj == nil { + return nil + } + + tn, typeOK := obj.(*types.TypeName) + if !typeOK { + return nil + } + + return tn.Type() +} + // shouldReportMissingAllowImplicit returns true when the provided 3rd argument // expression should trigger the "missing AllowImplicit" diagnostic, and false // when the argument is known to have AllowImplicit set (or when we must stay @@ -169,6 +295,398 @@ func isAllowImplicitSelector(s *ast.SelectorExpr) bool { return s != nil && s.Sel != nil && s.Sel.Name == allowImplicitFieldName } +// shouldReportQueryConcatenation returns true when the query string argument +// appears to be built using concatenation or fmt.Sprintf, which could lead to +// SQL injection vulnerabilities. Returns false when the query is a static string +// or we cannot determine its construction (conservative approach). +func shouldReportQueryConcatenation( + arg ast.Expr, + pass *analysis.Pass, + stack []ast.Node, + callPos token.Pos, +) bool { + // Direct concatenation: "query" + var + if isConcatenatedString(arg) { + return true + } + + // fmt.Sprintf call + if isFmtSprintfCall(arg, pass) { + return true + } + + // Variable that was assigned a concatenated string + if ident, ok := arg.(*ast.Ident); ok { + return wasBuiltWithConcatenation(ident, pass, stack, callPos) + } + + // Conservative: unknown expression shape, don't report + return false +} + +// isConcatenatedString checks if expr is a binary expression using + operator +// that involves at least one non-literal operand (indicating variable interpolation). +func isConcatenatedString(expr ast.Expr) bool { + expr = unwrapParens(expr) + + binExpr, ok := expr.(*ast.BinaryExpr) + if !ok { + return false + } + + if binExpr.Op != token.ADD { + return false + } + + // Recursively check both sides + leftIsAllLiteral := isAllStringLiterals(binExpr.X) + rightIsAllLiteral := isAllStringLiterals(binExpr.Y) + + // If both sides are only string literals (recursively), this is safe static concatenation + if leftIsAllLiteral && rightIsAllLiteral { + return false + } + + // At least one side involves non-literal content, so it's unsafe + return true +} + +// isAllStringLiterals recursively checks if expr consists only of string literals +// (including nested concatenations of string literals). +func isAllStringLiterals(expr ast.Expr) bool { + expr = unwrapParens(expr) + + // Base case: string literal + if isStringLiteral(expr) { + return true + } + + // Recursive case: binary expression with + + if binExpr, ok := expr.(*ast.BinaryExpr); ok && binExpr.Op == token.ADD { + return isAllStringLiterals(binExpr.X) && isAllStringLiterals(binExpr.Y) + } + + // Anything else (ident, call, etc.) is not a literal + return false +} + +// isStringLiteral checks if expr is a basic string literal (unwrapping parens). +func isStringLiteral(expr ast.Expr) bool { + expr = unwrapParens(expr) + lit, ok := expr.(*ast.BasicLit) + + return ok && lit.Kind == token.STRING +} + +// isFmtSprintfCall checks if expr is a call to fmt.Sprintf or similar formatting function. +func isFmtSprintfCall(expr ast.Expr, pass *analysis.Pass) bool { + expr = unwrapParens(expr) + + call, isCallExpr := expr.(*ast.CallExpr) + if !isCallExpr { + return false + } + + selExpr, isSelectorExpr := call.Fun.(*ast.SelectorExpr) + if !isSelectorExpr { + return false + } + + // Check if it's a Sprintf-like method + methodName := selExpr.Sel.Name + if methodName != "Sprintf" { + return false + } + + // Check if the receiver is from the fmt package + if ident, isIdent := selExpr.X.(*ast.Ident); isIdent { + if obj := pass.TypesInfo.ObjectOf(ident); obj != nil { + if pkgName, isPkgName := obj.(*types.PkgName); isPkgName { + return pkgName.Imported().Path() == fmtPackagePath + } + } + } + + return false +} + +// wasBuiltWithConcatenation checks if an identifier was assigned a value +// that involves string concatenation or fmt.Sprintf. +func wasBuiltWithConcatenation( + id *ast.Ident, + pass *analysis.Pass, + stack []ast.Node, + callPos token.Pos, +) bool { + obj := pass.TypesInfo.ObjectOf(id) + if obj == nil { + return false + } + + blocks := ancestorBlocks(stack) + + // Scan prior statements for assignments to this identifier + found := scanPriorStatements(blocks, callPos, func(stmt ast.Stmt) bool { + return stmtAssignsConcatenation(stmt, obj, pass) + }) + + if found { + return true + } + + // Check package-level variable declarations + return packageVarHasConcatenation(pass, obj) +} + +// stmtAssignsConcatenation checks if stmt assigns a concatenated string to the given object. +func stmtAssignsConcatenation(stmt ast.Stmt, obj types.Object, pass *analysis.Pass) bool { + // Handle regular assignment statements + if assign, isAssign := stmt.(*ast.AssignStmt); isAssign { + return assignStmtAssignsConcatenation(assign, obj, pass) + } + + // Handle var declarations with initialization + if declStmt, isDeclStmt := stmt.(*ast.DeclStmt); isDeclStmt { + return declStmtAssignsConcatenation(declStmt, obj, pass) + } + + // Handle control flow structures + switch stmtTyped := stmt.(type) { + case *ast.IfStmt: + return ifStmtAssignsConcatenation(stmtTyped, obj, pass) + case *ast.ForStmt: + return forStmtAssignsConcatenation(stmtTyped, obj, pass) + case *ast.RangeStmt: + return rangeStmtAssignsConcatenation(stmtTyped, obj, pass) + case *ast.SwitchStmt: + return switchStmtAssignsConcatenation(stmtTyped, obj, pass) + } + + return false +} + +// assignStmtAssignsConcatenation checks if an assignment statement assigns concatenation to obj. +func assignStmtAssignsConcatenation( + assign *ast.AssignStmt, + obj types.Object, + pass *analysis.Pass, +) bool { + for lhsIndex, lhs := range assign.Lhs { + lhsIdent, isIdent := lhs.(*ast.Ident) + if !isIdent { + continue + } + + if pass.TypesInfo.ObjectOf(lhsIdent) != obj { + continue + } + + // Find corresponding RHS + rhs := getRHSForLHS(assign, lhsIndex) + if rhs == nil { + continue + } + + // Check if RHS involves concatenation + if isConcatenatedString(rhs) || isFmtSprintfCall(rhs, pass) { + return true + } + + // Check for compound assignment (+=) + // Only flag if RHS is not a static string literal + if assign.Tok == token.ADD_ASSIGN { + // Safe if adding only static string literals + if !isStringLiteral(rhs) { + return true + } + } + } + + return false +} + +// getRHSForLHS returns the RHS expression corresponding to the LHS at the given index. +func getRHSForLHS(assign *ast.AssignStmt, lhsIndex int) ast.Expr { + switch { + case len(assign.Rhs) == len(assign.Lhs): + return assign.Rhs[lhsIndex] + case len(assign.Rhs) == 1: + return assign.Rhs[0] + default: + return nil + } +} + +// declStmtAssignsConcatenation checks if a declaration statement initializes obj with concatenation. +func declStmtAssignsConcatenation( + declStmt *ast.DeclStmt, + obj types.Object, + pass *analysis.Pass, +) bool { + genDecl, isGenDecl := declStmt.Decl.(*ast.GenDecl) + if !isGenDecl || genDecl.Tok != token.VAR { + return false + } + + for _, spec := range genDecl.Specs { + valueSpec, isValueSpec := spec.(*ast.ValueSpec) + if !isValueSpec { + continue + } + + if varDeclHasConcatenation(valueSpec, obj, pass) { + return true + } + } + + return false +} + +// varDeclHasConcatenation checks if a variable declaration initializes with concatenation. +func varDeclHasConcatenation(valueSpec *ast.ValueSpec, obj types.Object, pass *analysis.Pass) bool { + targetIndex := -1 + + for nameIndex, name := range valueSpec.Names { + if pass.TypesInfo.ObjectOf(name) == obj { + targetIndex = nameIndex + + break + } + } + + if targetIndex == -1 { + return false + } + + rhsValue := getRHSValueForIndex(valueSpec, targetIndex) + if rhsValue == nil { + return false + } + + return isConcatenatedString(rhsValue) || isFmtSprintfCall(rhsValue, pass) +} + +// getRHSValueForIndex returns the RHS value for a given index in a value spec. +func getRHSValueForIndex(valueSpec *ast.ValueSpec, targetIndex int) ast.Expr { + switch { + case targetIndex < len(valueSpec.Values): + return valueSpec.Values[targetIndex] + case len(valueSpec.Values) == 1: + return valueSpec.Values[0] + default: + return nil + } +} + +// packageVarHasConcatenation checks if a package-level variable is initialized with concatenation. +func packageVarHasConcatenation(pass *analysis.Pass, obj types.Object) bool { + for _, f := range pass.Files { + for _, decl := range f.Decls { + genDecl, ok := decl.(*ast.GenDecl) + if !ok || genDecl.Tok != token.VAR { + continue + } + + for _, spec := range genDecl.Specs { + valueSpec, ok := spec.(*ast.ValueSpec) + if !ok { + continue + } + + if varDeclHasConcatenation(valueSpec, obj, pass) { + return true + } + } + } + } + + return false +} + +// Control flow helpers for concatenation detection. +func ifStmtAssignsConcatenation(stmt *ast.IfStmt, obj types.Object, pass *analysis.Pass) bool { + for _, s := range stmt.Body.List { + if stmtAssignsConcatenation(s, obj, pass) { + return true + } + } + + if stmt.Else != nil { + switch elseNode := stmt.Else.(type) { + case *ast.BlockStmt: + for _, s := range elseNode.List { + if stmtAssignsConcatenation(s, obj, pass) { + return true + } + } + case *ast.IfStmt: + if stmtAssignsConcatenation(elseNode, obj, pass) { + return true + } + } + } + + return false +} + +func forStmtAssignsConcatenation(stmt *ast.ForStmt, obj types.Object, pass *analysis.Pass) bool { + if assign, ok := stmt.Init.(*ast.AssignStmt); ok { + if stmtAssignsConcatenation(assign, obj, pass) { + return true + } + } + + for _, s := range stmt.Body.List { + if stmtAssignsConcatenation(s, obj, pass) { + return true + } + } + + return false +} + +func rangeStmtAssignsConcatenation( + stmt *ast.RangeStmt, + obj types.Object, + pass *analysis.Pass, +) bool { + if stmt == nil || stmt.Body == nil { + return false + } + + for _, s := range stmt.Body.List { + if stmtAssignsConcatenation(s, obj, pass) { + return true + } + } + + return false +} + +func switchStmtAssignsConcatenation( + stmt *ast.SwitchStmt, + obj types.Object, + pass *analysis.Pass, +) bool { + if assign, ok := stmt.Init.(*ast.AssignStmt); ok { + if stmtAssignsConcatenation(assign, obj, pass) { + return true + } + } + + for _, cc := range stmt.Body.List { + if clause, ok := cc.(*ast.CaseClause); ok { + for _, s := range clause.Body { + if stmtAssignsConcatenation(s, obj, pass) { + return true + } + } + } + } + + return false +} + // isBeginTransaction reports whether call is a call to arangodb.Database.BeginTransaction. // It prefers selection-based detection via TypesInfo.Selections to support wrappers or // types that embed arangodb.Database. If selection info is unavailable, it falls back diff --git a/tools/vendor/modules.txt b/tools/vendor/modules.txt index 5f120206c..58e81e3d0 100644 --- a/tools/vendor/modules.txt +++ b/tools/vendor/modules.txt @@ -7,6 +7,9 @@ # codeberg.org/chavacava/garif v0.2.0 ## explicit; go 1.23 codeberg.org/chavacava/garif +# codeberg.org/polyfloyd/go-errorlint v1.9.0 +## explicit; go 1.24.0 +codeberg.org/polyfloyd/go-errorlint/errorlint # dev.gaijin.team/go/exhaustruct/v4 v4.0.0 ## explicit; go 1.24 dev.gaijin.team/go/exhaustruct/v4/analyzer @@ -54,10 +57,11 @@ github.com/Djarvur/go-err113 # github.com/Masterminds/semver/v3 v3.4.0 ## explicit; go 1.21 github.com/Masterminds/semver/v3 -# github.com/MirrexOne/unqueryvet v1.3.0 +# github.com/MirrexOne/unqueryvet v1.4.0 ## explicit; go 1.24.0 github.com/MirrexOne/unqueryvet github.com/MirrexOne/unqueryvet/internal/analyzer +github.com/MirrexOne/unqueryvet/internal/analyzer/sqlbuilders github.com/MirrexOne/unqueryvet/pkg/config # github.com/OpenPeeDeeP/depguard/v2 v2.2.1 ## explicit; go 1.23.0 @@ -78,8 +82,8 @@ github.com/alecthomas/go-check-sumtype # github.com/alexkohler/nakedret/v2 v2.0.6 ## explicit; go 1.23.0 github.com/alexkohler/nakedret/v2 -# github.com/alexkohler/prealloc v1.0.0 -## explicit; go 1.15 +# github.com/alexkohler/prealloc v1.0.1 +## explicit; go 1.24.0 github.com/alexkohler/prealloc/pkg # github.com/alfatraining/structtag v1.0.0 ## explicit; go 1.22 @@ -234,7 +238,7 @@ github.com/fzipp/gocyclo # github.com/ghostiam/protogetter v0.3.18 ## explicit; go 1.24.0 github.com/ghostiam/protogetter -# github.com/go-critic/go-critic v0.14.2 +# github.com/go-critic/go-critic v0.14.3 ## explicit; go 1.24.0 github.com/go-critic/go-critic/checkers github.com/go-critic/go-critic/checkers/internal/astwalk @@ -279,8 +283,8 @@ github.com/gobwas/glob/syntax/ast github.com/gobwas/glob/syntax/lexer github.com/gobwas/glob/util/runes github.com/gobwas/glob/util/strings -# github.com/godoc-lint/godoc-lint v0.10.2 -## explicit; go 1.24 +# github.com/godoc-lint/godoc-lint v0.11.1 +## explicit; go 1.24.0 github.com/godoc-lint/godoc-lint/pkg/analysis github.com/godoc-lint/godoc-lint/pkg/check github.com/godoc-lint/godoc-lint/pkg/check/deprecated @@ -290,6 +294,8 @@ github.com/godoc-lint/godoc-lint/pkg/check/pkg_doc github.com/godoc-lint/godoc-lint/pkg/check/require_doc github.com/godoc-lint/godoc-lint/pkg/check/shared github.com/godoc-lint/godoc-lint/pkg/check/start_with_name +github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink +github.com/godoc-lint/godoc-lint/pkg/check/stdlib_doclink/internal github.com/godoc-lint/godoc-lint/pkg/compose github.com/godoc-lint/godoc-lint/pkg/config github.com/godoc-lint/godoc-lint/pkg/inspect @@ -315,7 +321,7 @@ github.com/golangci/go-printf-func-name/pkg/analyzer # github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d ## explicit; go 1.22.0 github.com/golangci/gofmt/gofmt -# github.com/golangci/golangci-lint/v2 v2.7.2 +# github.com/golangci/golangci-lint/v2 v2.8.0 ## explicit; go 1.24.0 github.com/golangci/golangci-lint/v2/cmd/golangci-lint github.com/golangci/golangci-lint/v2/internal/cache @@ -484,9 +490,14 @@ github.com/golangci/golangci-lint/v2/pkg/report github.com/golangci/golangci-lint/v2/pkg/result github.com/golangci/golangci-lint/v2/pkg/result/processors github.com/golangci/golangci-lint/v2/pkg/timeutils -# github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 -## explicit; go 1.22.0 -github.com/golangci/golines +# github.com/golangci/golines v0.14.0 +## explicit; go 1.24.0 +github.com/golangci/golines/shorten +github.com/golangci/golines/shorten/internal +github.com/golangci/golines/shorten/internal/annotation +github.com/golangci/golines/shorten/internal/comments +github.com/golangci/golines/shorten/internal/graph +github.com/golangci/golines/shorten/internal/tags # github.com/golangci/misspell v0.7.0 ## explicit; go 1.23.0 github.com/golangci/misspell @@ -583,6 +594,9 @@ github.com/ldez/gomoddirectives ## explicit; go 1.24.0 github.com/ldez/grignotin/goenv github.com/ldez/grignotin/gomod +# github.com/ldez/structtags v0.6.1 +## explicit; go 1.24.0 +github.com/ldez/structtags/parser # github.com/ldez/tagliatelle v0.7.2 ## explicit; go 1.23.0 github.com/ldez/tagliatelle @@ -663,7 +677,7 @@ github.com/nishanths/exhaustive # github.com/nishanths/predeclared v0.2.2 ## explicit; go 1.14 github.com/nishanths/predeclared/passes/predeclared -# github.com/nunnatsa/ginkgolinter v0.21.2 +# github.com/nunnatsa/ginkgolinter v0.22.0 ## explicit; go 1.24.0 github.com/nunnatsa/ginkgolinter github.com/nunnatsa/ginkgolinter/config @@ -693,9 +707,6 @@ github.com/pelletier/go-toml/v2/unstable # github.com/pmezard/go-difflib v1.0.0 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/polyfloyd/go-errorlint v1.8.0 -## explicit; go 1.23.0 -github.com/polyfloyd/go-errorlint/errorlint # github.com/prometheus/client_golang v1.23.2 ## explicit; go 1.23.0 github.com/prometheus/client_golang/prometheus @@ -907,7 +918,7 @@ go-simpler.org/musttag # go-simpler.org/sloglint v0.11.1 ## explicit; go 1.23.0 go-simpler.org/sloglint -# go.augendre.info/arangolint v0.3.1 +# go.augendre.info/arangolint v0.4.0 ## explicit; go 1.24.0 go.augendre.info/arangolint/pkg/analyzer # go.augendre.info/fatcontext v0.9.0 @@ -952,7 +963,7 @@ golang.org/x/mod/sumdb/dirhash ## explicit; go 1.24.0 golang.org/x/sync/errgroup golang.org/x/sync/semaphore -# golang.org/x/sys v0.39.0 +# golang.org/x/sys v0.40.0 ## explicit; go 1.24.0 golang.org/x/sys/unix golang.org/x/sys/windows diff --git a/vendor/github.com/pulumi/esc/.version b/vendor/github.com/pulumi/esc/.version index 5a03fb737..885415662 100644 --- a/vendor/github.com/pulumi/esc/.version +++ b/vendor/github.com/pulumi/esc/.version @@ -1 +1 @@ -0.20.0 +0.21.0 diff --git a/vendor/github.com/pulumi/esc/CHANGELOG.md b/vendor/github.com/pulumi/esc/CHANGELOG.md index 2143da3e9..95acaa632 100644 --- a/vendor/github.com/pulumi/esc/CHANGELOG.md +++ b/vendor/github.com/pulumi/esc/CHANGELOG.md @@ -1,5 +1,14 @@ # CHANGELOG +## 0.21.0 + +### Improvements + +- Added support for `fn::split` built-in function to split strings into arrays. + [#281](https://github.com/pulumi/esc/issues/281) +- Add native support for OIDC token exchange when logging into Pulumi Cloud. Run `esc login --help` for more + information. [#607](https://github.com/pulumi/esc/pull/607) + ## 0.20.0 ### Improvements @@ -75,14 +84,14 @@ ### Bug Fixes - Fix `esc version` - [#541](https://github.com/pulumi/esc/pull/541) + [#541](https://github.com/pulumi/esc/pull/541) ## 0.13.2 ### Bug Fixes - handle nil in MakeSecret - [#518](https://github.com/pulumi/esc/pull/518) + [#518](https://github.com/pulumi/esc/pull/518) ## 0.13.1 @@ -224,7 +233,6 @@ - Add support for displaying changed between environment revisions. [#295](https://github.com/pulumi/esc/pull/295) - - Finalize command tree for version management. [#304](https://github.com/pulumi/esc/pull/304) @@ -295,7 +303,7 @@ - Add support for execution context interpolation. [#239](https://github.com/pulumi/esc/pull/239) - + ## 0.7.0 ### Bug Fixes @@ -326,7 +334,6 @@ - Include paths in diagnostics. [#157](https://github.com/pulumi/esc/pull/157) - - Support secret elision in definitions via encryption and decryption [#155](https://github.com/pulumi/esc/pull/155) @@ -352,7 +359,6 @@ - Do not panic when `env set` is passed an empty value. [#110](https://github.com/pulumi/esc/pull/110) - - Fix behavior for `esc login` when no existing credentials are present [#111](https://github.com/pulumi/esc/pull/111) diff --git a/vendor/github.com/pulumi/esc/CHANGELOG_PENDING.md b/vendor/github.com/pulumi/esc/CHANGELOG_PENDING.md index 83807f6ae..ab086590d 100644 --- a/vendor/github.com/pulumi/esc/CHANGELOG_PENDING.md +++ b/vendor/github.com/pulumi/esc/CHANGELOG_PENDING.md @@ -1,13 +1,10 @@ ### Improvements -- Added deletion protection for environments: - - Use `esc env settings set [/][/] deletion-protected true` to enable deletion protection - - Use `esc env settings get [/][/] [deletion-protected]` to check the current status - - When enabled, environments cannot be deleted until protection is disabled - - Deletion protection is disabled by default for new environments +- Added support for `fn::split` built-in function to split strings into arrays. + [#281](https://github.com/pulumi/esc/issues/281) +- Add native support for OIDC token exchange when logging into Pulumi Cloud. Run `esc login --help` for more + information. [#607](https://github.com/pulumi/esc/pull/607) ### Bug Fixes -- Environment declarations are now returned even in the face of syntax errors. - ### Breaking changes diff --git a/vendor/github.com/pulumi/esc/ast/expr.go b/vendor/github.com/pulumi/esc/ast/expr.go index 8b909fe52..ef5155e3c 100644 --- a/vendor/github.com/pulumi/esc/ast/expr.go +++ b/vendor/github.com/pulumi/esc/ast/expr.go @@ -574,6 +574,31 @@ func Concat(arrays *ArrayExpr) *ConcatExpr { } } +// SplitExpr splits a string on a delimiter into an array of strings. +type SplitExpr struct { + builtinNode + + Delimiter Expr + String Expr +} + +func SplitSyntax(node *syntax.ObjectNode, name *StringExpr, args, delimiter, str Expr) *SplitExpr { + return &SplitExpr{ + builtinNode: builtin(node, name, args), + Delimiter: delimiter, + String: str, + } +} + +func Split(delimiter Expr, str Expr) *SplitExpr { + name := String("fn::split") + return &SplitExpr{ + builtinNode: builtin(nil, name, Array(delimiter, str)), + Delimiter: delimiter, + String: str, + } +} + type SecretExpr struct { builtinNode @@ -676,6 +701,8 @@ func tryParseFunction(node *syntax.ObjectNode) (Expr, syntax.Diagnostics, bool) parse = parseRotate case "fn::secret": parse = parseSecret + case "fn::split": + parse = parseSplit case "fn::toBase64": parse = parseToBase64 case "fn::toJSON": @@ -869,6 +896,16 @@ func parseJoin(node *syntax.ObjectNode, name *StringExpr, args Expr) (Expr, synt return JoinSyntax(node, name, list, list.Elements[0], list.Elements[1]), nil } +func parseSplit(node *syntax.ObjectNode, name *StringExpr, args Expr) (Expr, syntax.Diagnostics) { + list, ok := args.(*ArrayExpr) + if !ok || len(list.Elements) != 2 { + diags := syntax.Diagnostics{ExprError(args, "the argument to fn::split must be a two-valued list")} + return SplitSyntax(node, name, args, nil, nil), diags + } + + return SplitSyntax(node, name, list, list.Elements[0], list.Elements[1]), nil +} + func parseToJSON(node *syntax.ObjectNode, name *StringExpr, args Expr) (Expr, syntax.Diagnostics) { return ToJSONSyntax(node, name, args), nil } diff --git a/vendor/github.com/pulumi/esc/eval/crypt.go b/vendor/github.com/pulumi/esc/eval/crypt.go index ee1c9fd91..00be3e843 100644 --- a/vendor/github.com/pulumi/esc/eval/crypt.go +++ b/vendor/github.com/pulumi/esc/eval/crypt.go @@ -119,10 +119,11 @@ func EncryptSecrets(ctx context.Context, filename string, source []byte, encrypt } // Encrypt the plaintext. - ciphertext, err := encrypter.Encrypt(ctx, []byte(plaintext.Value())) + ciphertext, err := EncryptSecret(ctx, encrypter, []byte(plaintext.Value())) if err != nil { return nil, nil, err } + encodedCiphertext := base64.StdEncoding.EncodeToString(ciphertext) // Replace the original call to `fn::secret` with a new call whose argument is the encrypted ciphertext. // @@ -134,7 +135,7 @@ func EncryptSecrets(ctx context.Context, filename string, source []byte, encrypt syntax.Object( syntax.ObjectProperty( syntax.String("ciphertext"), - syntax.StringSyntax(syntax.CopyTrivia(plaintext.Syntax()), encodeCiphertext(ciphertext)), + syntax.StringSyntax(syntax.CopyTrivia(plaintext.Syntax()), encodedCiphertext), ), ), ), @@ -161,12 +162,7 @@ func DecryptSecrets(ctx context.Context, filename string, source []byte, decrypt return n, nil, nil } - ciphertext, err := decodeCiphertext(ciphertextNode.Value()) - if err != nil { - return nil, nil, fmt.Errorf("invalid ciphertext: %w", err) - } - - plaintext, err := decrypter.Decrypt(ctx, ciphertext) + plaintext, err := DecryptSecret(ctx, decrypter, ciphertextNode.Value()) if err != nil { return nil, nil, err } @@ -178,6 +174,26 @@ func DecryptSecrets(ctx context.Context, filename string, source []byte, decrypt }) } +// EncryptSecret encrypts a given secret and returns the encoded ciphertext +func EncryptSecret(ctx context.Context, encrypter Encrypter, plaintext []byte) ([]byte, error) { + ciphertext, err := encrypter.Encrypt(ctx, plaintext) + if err != nil { + return nil, err + } + + return encodeCiphertext(ciphertext), nil +} + +// DecryptSecret decrypts a given encoded ciphertext and returns the plaintext +func DecryptSecret(ctx context.Context, decrypter Decrypter, encodedCiphertext string) ([]byte, error) { + ciphertext, err := decodeCiphertext(encodedCiphertext) + if err != nil { + return nil, fmt.Errorf("invalid ciphertext: %w", err) + } + + return decrypter.Decrypt(ctx, ciphertext) +} + const envelopeMagic = "escx" const envelopeVersion = uint32(1) @@ -223,11 +239,11 @@ func decodeCiphertext(repr string) ([]byte, error) { return bin[8 : len(bin)-4], nil } -func encodeCiphertext(ciphertext []byte) string { +func encodeCiphertext(ciphertext []byte) []byte { var b bytes.Buffer b.WriteString(envelopeMagic) // "escx" b.Write(binary.BigEndian.AppendUint32(nil, envelopeVersion)) // version b.Write(ciphertext) // ciphertext b.Write(binary.BigEndian.AppendUint32(nil, crc32.Checksum(b.Bytes(), crc32.IEEETable))) // crc32 - return base64.StdEncoding.EncodeToString(b.Bytes()) + return b.Bytes() } diff --git a/vendor/github.com/pulumi/esc/eval/eval.go b/vendor/github.com/pulumi/esc/eval/eval.go index f3aa93fb3..e6372ebfa 100644 --- a/vendor/github.com/pulumi/esc/eval/eval.go +++ b/vendor/github.com/pulumi/esc/eval/eval.go @@ -341,6 +341,13 @@ func declare[Expr exprNode](e *evalContext, path string, x Expr, base *value) *e values: declare(e, "", x.Values, nil), } return newExpr(path, repr, schema.String().Schema(), base) + case *ast.SplitExpr: + repr := &splitExpr{ + node: x, + delimiter: declare(e, "", x.Delimiter, nil), + string: declare(e, "", x.String, nil), + } + return newExpr(path, repr, schema.Array().Items(schema.String()).Schema(), base) case *ast.OpenExpr: repr := &openExpr{ node: x, @@ -599,6 +606,8 @@ func (e *evalContext) evaluateExpr(x *expr, accept *schema.Schema) *value { val = e.evaluateBuiltinFromJSON(x, repr) case *joinExpr: val = e.evaluateBuiltinJoin(x, repr) + case *splitExpr: + val = e.evaluateBuiltinSplit(x, repr) case *openExpr: val = e.evaluateBuiltinOpen(x, repr) case *rotateExpr: @@ -1271,6 +1280,29 @@ func (e *evalContext) evaluateBuiltinJoin(x *expr, repr *joinExpr) *value { return v } +// evaluateBuiltinSplit evaluates a call to the fn::split builtin. +func (e *evalContext) evaluateBuiltinSplit(x *expr, repr *splitExpr) *value { + v := &value{def: x, schema: x.schema} + + delim, delimOk := e.evaluateTypedExpr(repr.delimiter, schema.String().Schema()) + str, strOk := e.evaluateTypedExpr(repr.string, schema.String().Schema()) + if !delimOk || !strOk { + v.unknown = true + return v + } + + v.combine(delim, str) + if !v.unknown { + parts := strings.Split(str.repr.(string), delim.repr.(string)) + result := make([]*value, len(parts)) + for i, part := range parts { + result[i] = &value{def: x, schema: schema.String().Schema(), repr: part} + } + v.repr = result + } + return v +} + // evaluateBuiltinFromBase64 evaluates a call from the fn::fromBase64 builtin. func (e *evalContext) evaluateBuiltinFromBase64(x *expr, repr *fromBase64Expr) *value { v := &value{def: x, schema: x.schema} diff --git a/vendor/github.com/pulumi/esc/eval/expr.go b/vendor/github.com/pulumi/esc/eval/expr.go index deea81074..ca4357a83 100644 --- a/vendor/github.com/pulumi/esc/eval/expr.go +++ b/vendor/github.com/pulumi/esc/eval/expr.go @@ -193,6 +193,17 @@ func (x *expr) export(environment string) esc.Expr { List: []esc.Expr{repr.delimiter.export(environment), repr.values.export(environment)}, }, } + case *splitExpr: + argRange := convertRange(repr.node.Args().Syntax().Syntax().Range(), environment) + ex.Builtin = &esc.BuiltinExpr{ + Name: repr.node.Name().Value, + NameRange: convertRange(repr.node.Name().Syntax().Syntax().Range(), environment), + ArgSchema: schema.Tuple(schema.String(), schema.String()).Schema(), + Arg: esc.Expr{ + Range: argRange, + List: []esc.Expr{repr.delimiter.export(environment), repr.string.export(environment)}, + }, + } case *openExpr: name := repr.node.Name().Value if name == "fn::open" { @@ -483,6 +494,18 @@ func (x *joinExpr) syntax() ast.Expr { return x.node } +// splitExpr represents a call to the fn::split builtin. +type splitExpr struct { + node *ast.SplitExpr + + delimiter *expr + string *expr +} + +func (x *splitExpr) syntax() ast.Expr { + return x.node +} + // concatExpr represents a call to the fn::concat builtin. type concatExpr struct { node *ast.ConcatExpr diff --git a/vendor/github.com/pulumi/esc/eval/patch.go b/vendor/github.com/pulumi/esc/eval/patch.go index e7562bc5f..a9b12c5b5 100644 --- a/vendor/github.com/pulumi/esc/eval/patch.go +++ b/vendor/github.com/pulumi/esc/eval/patch.go @@ -15,6 +15,8 @@ package eval import ( + "encoding/json" + "github.com/pulumi/esc" "github.com/pulumi/esc/syntax/encoding" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" @@ -42,7 +44,10 @@ func ApplyValuePatches(source []byte, patches []*Patch) ([]byte, error) { } // convert the esc.Value into a yaml node that can be set on the environment - replacement := valueToSecretJSON(patch.Replacement) + replacement, err := valueToSecretJSON(patch.Replacement) + if err != nil { + return nil, err + } bytes, err := yaml.Marshal(replacement) if err != nil { return nil, err @@ -63,30 +68,55 @@ func ApplyValuePatches(source []byte, patches []*Patch) ([]byte, error) { } // valueToSecretJSON converts a Value into a plain-old-JSON value, but secret values are wrapped with fn::secret -func valueToSecretJSON(v esc.Value) any { - ret := func() any { - switch pv := v.Value.(type) { - case []esc.Value: - a := make([]any, len(pv)) - for i, v := range pv { - a[i] = valueToSecretJSON(v) +func valueToSecretJSON(v esc.Value) (any, error) { + // If this value is secret at the top level, we need to handle it specially + // to avoid nested fn::secret calls and to properly encode non-primitive secrets + if v.Secret { + return wrapSecret(v.ToJSON(false)) + } + + // For non-secret values, recurse normally + var err error + switch pv := v.Value.(type) { + case []esc.Value: + a := make([]any, len(pv)) + for i, v := range pv { + a[i], err = valueToSecretJSON(v) + if err != nil { + return nil, err } - return a - case map[string]esc.Value: - m := make(map[string]any, len(pv)) - for k, v := range pv { - m[k] = valueToSecretJSON(v) + } + return a, nil + case map[string]esc.Value: + m := make(map[string]any, len(pv)) + for k, v := range pv { + m[k], err = valueToSecretJSON(v) + if err != nil { + return nil, err } - return m - default: - return pv } - }() - // wrap secret values - if v.Secret { + return m, nil + default: + return pv, nil + } +} + +// wrapSecret wraps a value in a fn::secret function call +func wrapSecret(v any) (any, error) { + if _, ok := v.(string); ok { return map[string]any{ - "fn::secret": ret, - } + "fn::secret": v, + }, nil + } + + // fn::secret requires a string literal, so encode any non-strings as a JSON + encoded, err := json.Marshal(v) + if err != nil { + return nil, err } - return ret + return map[string]any{ + "fn::fromJSON": map[string]any{ + "fn::secret": string(encoded), + }, + }, nil } diff --git a/vendor/github.com/pulumi/pulumi-aws-native/sdk/go/aws/internal/pulumiUtilities.go b/vendor/github.com/pulumi/pulumi-aws-native/sdk/go/aws/internal/pulumiUtilities.go index 912314d7f..c8bde852d 100644 --- a/vendor/github.com/pulumi/pulumi-aws-native/sdk/go/aws/internal/pulumiUtilities.go +++ b/vendor/github.com/pulumi/pulumi-aws-native/sdk/go/aws/internal/pulumiUtilities.go @@ -165,7 +165,7 @@ func callPlainInner( func PkgResourceDefaultOpts(opts []pulumi.ResourceOption) []pulumi.ResourceOption { defaults := []pulumi.ResourceOption{} - version := semver.MustParse("1.45.0") + version := semver.MustParse("1.47.0") if !version.Equals(semver.Version{}) { defaults = append(defaults, pulumi.Version(version.String())) } @@ -176,7 +176,7 @@ func PkgResourceDefaultOpts(opts []pulumi.ResourceOption) []pulumi.ResourceOptio func PkgInvokeDefaultOpts(opts []pulumi.InvokeOption) []pulumi.InvokeOption { defaults := []pulumi.InvokeOption{} - version := semver.MustParse("1.45.0") + version := semver.MustParse("1.47.0") if !version.Equals(semver.Version{}) { defaults = append(defaults, pulumi.Version(version.String())) } diff --git a/vendor/github.com/pulumi/pulumi-aws-native/sdk/go/aws/pulumi-plugin.json b/vendor/github.com/pulumi/pulumi-aws-native/sdk/go/aws/pulumi-plugin.json index 82aab3b70..7b334bfdf 100644 --- a/vendor/github.com/pulumi/pulumi-aws-native/sdk/go/aws/pulumi-plugin.json +++ b/vendor/github.com/pulumi/pulumi-aws-native/sdk/go/aws/pulumi-plugin.json @@ -1,5 +1,5 @@ { "resource": true, "name": "aws-native", - "version": "1.45.0" + "version": "1.47.0" } diff --git a/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/internal/pulumiUtilities.go b/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/internal/pulumiUtilities.go index bcd900037..447e4f4ba 100644 --- a/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/internal/pulumiUtilities.go +++ b/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/internal/pulumiUtilities.go @@ -165,7 +165,7 @@ func callPlainInner( func PkgResourceDefaultOpts(opts []pulumi.ResourceOption) []pulumi.ResourceOption { defaults := []pulumi.ResourceOption{} - version := semver.MustParse("4.10.0") + version := semver.MustParse("4.11.0") if !version.Equals(semver.Version{}) { defaults = append(defaults, pulumi.Version(version.String())) } @@ -176,7 +176,7 @@ func PkgResourceDefaultOpts(opts []pulumi.ResourceOption) []pulumi.ResourceOptio func PkgInvokeDefaultOpts(opts []pulumi.InvokeOption) []pulumi.InvokeOption { defaults := []pulumi.InvokeOption{} - version := semver.MustParse("4.10.0") + version := semver.MustParse("4.11.0") if !version.Equals(semver.Version{}) { defaults = append(defaults, pulumi.Version(version.String())) } diff --git a/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/pulumi-plugin.json b/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/pulumi-plugin.json index 4ebffe9ba..0129791c0 100644 --- a/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/pulumi-plugin.json +++ b/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/pulumi-plugin.json @@ -1,5 +1,5 @@ { "resource": true, "name": "docker", - "version": "4.10.0" + "version": "4.11.0" } diff --git a/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/pulumiTypes.go b/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/pulumiTypes.go index 86619fcae..f37e31400 100644 --- a/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/pulumiTypes.go +++ b/vendor/github.com/pulumi/pulumi-docker/sdk/v4/go/docker/pulumiTypes.go @@ -4466,7 +4466,7 @@ func (o RegistryImageAuthConfigPtrOutput) Username() pulumi.StringPtrOutput { type RegistryImageBuild struct { // A list of additional build contexts. Only supported when using a buildx builder. Example: `["name=path", "src = https://example.org"}`. Please see https://docs.docker.com/reference/cli/docker/buildx/build/#build-context for more information. AdditionalContexts []string `pulumi:"additionalContexts"` - // Authentication configuration for the Docker registry. It is only used for this resource. + // The configuration for the authentication AuthConfigs []RegistryImageBuildAuthConfig `pulumi:"authConfigs"` // Pairs for build-time variables in the form of `ENDPOINT : "https://example.com"` BuildArgs map[string]string `pulumi:"buildArgs"` @@ -4558,7 +4558,7 @@ type RegistryImageBuildInput interface { type RegistryImageBuildArgs struct { // A list of additional build contexts. Only supported when using a buildx builder. Example: `["name=path", "src = https://example.org"}`. Please see https://docs.docker.com/reference/cli/docker/buildx/build/#build-context for more information. AdditionalContexts pulumi.StringArrayInput `pulumi:"additionalContexts"` - // Authentication configuration for the Docker registry. It is only used for this resource. + // The configuration for the authentication AuthConfigs RegistryImageBuildAuthConfigArrayInput `pulumi:"authConfigs"` // Pairs for build-time variables in the form of `ENDPOINT : "https://example.com"` BuildArgs pulumi.StringMapInput `pulumi:"buildArgs"` @@ -4718,7 +4718,7 @@ func (o RegistryImageBuildOutput) AdditionalContexts() pulumi.StringArrayOutput return o.ApplyT(func(v RegistryImageBuild) []string { return v.AdditionalContexts }).(pulumi.StringArrayOutput) } -// Authentication configuration for the Docker registry. It is only used for this resource. +// The configuration for the authentication func (o RegistryImageBuildOutput) AuthConfigs() RegistryImageBuildAuthConfigArrayOutput { return o.ApplyT(func(v RegistryImageBuild) []RegistryImageBuildAuthConfig { return v.AuthConfigs }).(RegistryImageBuildAuthConfigArrayOutput) } @@ -4942,7 +4942,7 @@ func (o RegistryImageBuildPtrOutput) AdditionalContexts() pulumi.StringArrayOutp }).(pulumi.StringArrayOutput) } -// Authentication configuration for the Docker registry. It is only used for this resource. +// The configuration for the authentication func (o RegistryImageBuildPtrOutput) AuthConfigs() RegistryImageBuildAuthConfigArrayOutput { return o.ApplyT(func(v *RegistryImageBuild) []RegistryImageBuildAuthConfig { if v == nil { @@ -5331,7 +5331,7 @@ type RegistryImageBuildAuthConfig struct { HostName string `pulumi:"hostName"` // the identity token IdentityToken *string `pulumi:"identityToken"` - // The password for the Docker registry. + // the registry password Password *string `pulumi:"password"` // the registry token RegistryToken *string `pulumi:"registryToken"` @@ -5361,7 +5361,7 @@ type RegistryImageBuildAuthConfigArgs struct { HostName pulumi.StringInput `pulumi:"hostName"` // the identity token IdentityToken pulumi.StringPtrInput `pulumi:"identityToken"` - // The password for the Docker registry. + // the registry password Password pulumi.StringPtrInput `pulumi:"password"` // the registry token RegistryToken pulumi.StringPtrInput `pulumi:"registryToken"` @@ -5442,7 +5442,7 @@ func (o RegistryImageBuildAuthConfigOutput) IdentityToken() pulumi.StringPtrOutp return o.ApplyT(func(v RegistryImageBuildAuthConfig) *string { return v.IdentityToken }).(pulumi.StringPtrOutput) } -// The password for the Docker registry. +// the registry password func (o RegistryImageBuildAuthConfigOutput) Password() pulumi.StringPtrOutput { return o.ApplyT(func(v RegistryImageBuildAuthConfig) *string { return v.Password }).(pulumi.StringPtrOutput) } @@ -5485,7 +5485,7 @@ func (o RegistryImageBuildAuthConfigArrayOutput) Index(i pulumi.IntInput) Regist type RegistryImageBuildSecret struct { // Environment variable source of the secret Env *string `pulumi:"env"` - // The ID of this resource. + // ID of the secret. By default, secrets are mounted to /run/secrets/\n\n Id string `pulumi:"id"` // File source of the secret. Takes precedence over `env` Src *string `pulumi:"src"` @@ -5505,7 +5505,7 @@ type RegistryImageBuildSecretInput interface { type RegistryImageBuildSecretArgs struct { // Environment variable source of the secret Env pulumi.StringPtrInput `pulumi:"env"` - // The ID of this resource. + // ID of the secret. By default, secrets are mounted to /run/secrets/\n\n Id pulumi.StringInput `pulumi:"id"` // File source of the secret. Takes precedence over `env` Src pulumi.StringPtrInput `pulumi:"src"` @@ -5567,7 +5567,7 @@ func (o RegistryImageBuildSecretOutput) Env() pulumi.StringPtrOutput { return o.ApplyT(func(v RegistryImageBuildSecret) *string { return v.Env }).(pulumi.StringPtrOutput) } -// The ID of this resource. +// ID of the secret. By default, secrets are mounted to /run/secrets/\n\n func (o RegistryImageBuildSecretOutput) Id() pulumi.StringOutput { return o.ApplyT(func(v RegistryImageBuildSecret) string { return v.Id }).(pulumi.StringOutput) } @@ -5600,7 +5600,7 @@ func (o RegistryImageBuildSecretArrayOutput) Index(i pulumi.IntInput) RegistryIm type RegistryImageBuildUlimit struct { // soft limit Hard int `pulumi:"hard"` - // The name of the Docker image. + // type of ulimit, e.g. `nofile` Name string `pulumi:"name"` // hard limit Soft int `pulumi:"soft"` @@ -5620,7 +5620,7 @@ type RegistryImageBuildUlimitInput interface { type RegistryImageBuildUlimitArgs struct { // soft limit Hard pulumi.IntInput `pulumi:"hard"` - // The name of the Docker image. + // type of ulimit, e.g. `nofile` Name pulumi.StringInput `pulumi:"name"` // hard limit Soft pulumi.IntInput `pulumi:"soft"` @@ -5682,7 +5682,7 @@ func (o RegistryImageBuildUlimitOutput) Hard() pulumi.IntOutput { return o.ApplyT(func(v RegistryImageBuildUlimit) int { return v.Hard }).(pulumi.IntOutput) } -// The name of the Docker image. +// type of ulimit, e.g. `nofile` func (o RegistryImageBuildUlimitOutput) Name() pulumi.StringOutput { return o.ApplyT(func(v RegistryImageBuildUlimit) string { return v.Name }).(pulumi.StringOutput) } @@ -8607,7 +8607,7 @@ type ServiceTaskSpecContainerSpec struct { Env map[string]string `pulumi:"env"` // A list of additional groups that the container process will run as Groups []string `pulumi:"groups"` - // A test to perform to check that the container is healthy + // A test to perform to check that the container is healthy. It works in the same way, and has the same default values, as the HEALTHCHECK Dockerfile instruction set by the service's Docker image. Your Compose file can override the values set in the Dockerfile. Healthcheck *ServiceTaskSpecContainerSpecHealthcheck `pulumi:"healthcheck"` // The hostname to use for the container, as a valid RFC 1123 hostname Hostname *string `pulumi:"hostname"` @@ -8667,7 +8667,7 @@ type ServiceTaskSpecContainerSpecArgs struct { Env pulumi.StringMapInput `pulumi:"env"` // A list of additional groups that the container process will run as Groups pulumi.StringArrayInput `pulumi:"groups"` - // A test to perform to check that the container is healthy + // A test to perform to check that the container is healthy. It works in the same way, and has the same default values, as the HEALTHCHECK Dockerfile instruction set by the service's Docker image. Your Compose file can override the values set in the Dockerfile. Healthcheck ServiceTaskSpecContainerSpecHealthcheckPtrInput `pulumi:"healthcheck"` // The hostname to use for the container, as a valid RFC 1123 hostname Hostname pulumi.StringPtrInput `pulumi:"hostname"` @@ -8819,7 +8819,7 @@ func (o ServiceTaskSpecContainerSpecOutput) Groups() pulumi.StringArrayOutput { return o.ApplyT(func(v ServiceTaskSpecContainerSpec) []string { return v.Groups }).(pulumi.StringArrayOutput) } -// A test to perform to check that the container is healthy +// A test to perform to check that the container is healthy. It works in the same way, and has the same default values, as the HEALTHCHECK Dockerfile instruction set by the service's Docker image. Your Compose file can override the values set in the Dockerfile. func (o ServiceTaskSpecContainerSpecOutput) Healthcheck() ServiceTaskSpecContainerSpecHealthcheckPtrOutput { return o.ApplyT(func(v ServiceTaskSpecContainerSpec) *ServiceTaskSpecContainerSpecHealthcheck { return v.Healthcheck }).(ServiceTaskSpecContainerSpecHealthcheckPtrOutput) } @@ -9003,7 +9003,7 @@ func (o ServiceTaskSpecContainerSpecPtrOutput) Groups() pulumi.StringArrayOutput }).(pulumi.StringArrayOutput) } -// A test to perform to check that the container is healthy +// A test to perform to check that the container is healthy. It works in the same way, and has the same default values, as the HEALTHCHECK Dockerfile instruction set by the service's Docker image. Your Compose file can override the values set in the Dockerfile. func (o ServiceTaskSpecContainerSpecPtrOutput) Healthcheck() ServiceTaskSpecContainerSpecHealthcheckPtrOutput { return o.ApplyT(func(v *ServiceTaskSpecContainerSpec) *ServiceTaskSpecContainerSpecHealthcheck { if v == nil { diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/.version b/vendor/github.com/pulumi/pulumi/sdk/v3/.version index 7512b69cb..240dd3396 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/.version +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/.version @@ -1 +1 @@ -3.213.0 +3.215.0 diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/config/value.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/config/value.go index 3918106a4..a33b8fc6f 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/config/value.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/config/value.go @@ -1,4 +1,4 @@ -// Copyright 2016-2022, Pulumi Corporation. +// Copyright 2016-2025, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import ( "strconv" "github.com/pulumi/pulumi/sdk/v3/go/common/util/contract" + "github.com/pulumi/pulumi/sdk/v3/go/common/util/logging" ) type Type int @@ -182,7 +183,12 @@ func (c Value) unmarshalObject() (object, error) { } return newObject(int64(i)), nil case TypeBool: - return newObject(c.value == "true"), nil + b, err := strconv.ParseBool(c.value) + if err != nil { + logging.Warningf("Failed to parse boolean value '%s': %v. Defaulting to false.", c.value, err) + return newObject(false), nil + } + return newObject(b), nil case TypeFloat: f, err := strconv.ParseFloat(c.value, 64) if err != nil { diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/analyzer.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/analyzer.go index 97de2256d..224c7693b 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/analyzer.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/analyzer.go @@ -21,7 +21,6 @@ import ( "github.com/pulumi/pulumi/sdk/v3/go/common/apitype" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" "github.com/pulumi/pulumi/sdk/v3/go/common/tokens" - "github.com/pulumi/pulumi/sdk/v3/go/common/workspace" ) // AnalyzerPolicyType indicates the type of a policy. @@ -55,7 +54,7 @@ type Analyzer interface { // GetAnalyzerInfo returns metadata about the analyzer (e.g., list of policies contained). GetAnalyzerInfo() (AnalyzerInfo, error) // GetPluginInfo returns this plugin's information. - GetPluginInfo() (workspace.PluginInfo, error) + GetPluginInfo() (PluginInfo, error) // Configure configures the analyzer, passing configuration properties for each policy. Configure(policyConfig map[string]AnalyzerPolicyConfig) error // Cancel signals the analyzer to gracefully shut down and abort any ongoing analysis operations. diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/analyzer_plugin.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/analyzer_plugin.go index 396fd0677..eca964b2e 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/analyzer_plugin.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/analyzer_plugin.go @@ -605,34 +605,26 @@ func (a *analyzer) GetAnalyzerInfo() (AnalyzerInfo, error) { } // GetPluginInfo returns this plugin's information. -func (a *analyzer) GetPluginInfo() (workspace.PluginInfo, error) { +func (a *analyzer) GetPluginInfo() (PluginInfo, error) { label := a.label() + ".GetPluginInfo()" logging.V(7).Infof("%s executing", label) resp, err := a.client.GetPluginInfo(a.requestContext(), &emptypb.Empty{}) if err != nil { rpcError := rpcerror.Convert(err) logging.V(7).Infof("%s failed: err=%v", a.label(), rpcError) - return workspace.PluginInfo{}, rpcError + return PluginInfo{}, rpcError } var version *semver.Version if v := resp.Version; v != "" { sv, err := semver.ParseTolerant(v) if err != nil { - return workspace.PluginInfo{}, err + return PluginInfo{}, err } version = &sv } - path := "" - if a.plug != nil { - path = a.plug.Bin - } - - return workspace.PluginInfo{ - Name: string(a.name), - Path: path, - Kind: apitype.AnalyzerPlugin, + return PluginInfo{ Version: version, }, nil } diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/context.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/context.go index c0f228aaf..75f215492 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/context.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/context.go @@ -51,8 +51,7 @@ type Context struct { tracingSpan opentracing.Span // the OpenTracing span to parent requests within. - cancelFuncs []context.CancelFunc - cancelLock *sync.Mutex // Guards cancelFuncs. + cancel context.CancelFunc baseContext context.Context } @@ -104,6 +103,8 @@ func NewContextWithRoot(ctx context.Context, d, statusD diag.Sink, host Host, } } + ctx, cancel := context.WithCancel(ctx) + pctx := &Context{ Diag: d, StatusDiag: statusD, @@ -112,8 +113,8 @@ func NewContextWithRoot(ctx context.Context, d, statusD diag.Sink, host Host, Root: root, tracingSpan: parentSpan, DebugTraceMutex: &sync.Mutex{}, - cancelLock: &sync.Mutex{}, baseContext: ctx, + cancel: cancel, } if host == nil { h, err := NewDefaultHost( @@ -150,30 +151,13 @@ func (ctx *Context) Base() context.Context { // Request allocates a request sub-context. func (ctx *Context) Request() context.Context { - c := ctx.baseContext - contract.Assertf(c != nil, "Context must have a base context") - c = opentracing.ContextWithSpan(c, ctx.tracingSpan) - c, cancel := context.WithCancel(c) - ctx.cancelLock.Lock() - ctx.cancelFuncs = append(ctx.cancelFuncs, cancel) - ctx.cancelLock.Unlock() - return c + contract.Assertf(ctx.baseContext != nil, "Context must have a base context") + return opentracing.ContextWithSpan(ctx.baseContext, ctx.tracingSpan) } // Close reclaims all resources associated with this context. func (ctx *Context) Close() error { - defer func() { - // It is possible that cancelFuncs may be appended while this function is running. - // Capture the current value of cancelFuncs and set cancelFuncs to nil to prevent cancelFuncs - // from being appended to while we are iterating over it. - ctx.cancelLock.Lock() - cancelFuncs := ctx.cancelFuncs - ctx.cancelFuncs = nil - ctx.cancelLock.Unlock() - for _, cancel := range cancelFuncs { - cancel() - } - }() + defer ctx.cancel() if ctx.tracingSpan != nil { ctx.tracingSpan.Finish() } @@ -183,16 +167,3 @@ func (ctx *Context) Close() error { } return nil } - -// WithCancelChannel registers a close channel which will close the returned Context when -// the channel is closed. -// -// WARNING: Calling this function without ever closing `c` will leak go routines. -func (ctx *Context) WithCancelChannel(c <-chan struct{}) *Context { - newCtx := *ctx - go func() { - <-c - newCtx.Close() - }() - return &newCtx -} diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/host.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/host.go index b2b953c3a..b0e476fb7 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/host.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/host.go @@ -68,9 +68,7 @@ type Host interface { // Provider loads a new copy of the provider for a given package. If a provider for this package could not be // found, or an error occurs while creating it, a non-nil error is returned. - Provider(descriptor workspace.PackageDescriptor) (Provider, error) - // CloseProvider closes the given provider plugin and deregisters it from this host. - CloseProvider(provider Provider) error + Provider(descriptor workspace.PluginDescriptor) (Provider, error) // LanguageRuntime fetches the language runtime plugin for a given language, lazily allocating if necessary. If // an implementation of this language runtime wasn't found, on an error occurs, a non-nil error is returned. LanguageRuntime(runtime string) (LanguageRuntime, error) @@ -111,7 +109,7 @@ func IsLocalPluginPath(ctx context.Context, source string) bool { // For other cases, we need to be careful about how we interpret the source, so let's parse the spec // and check if it has a download URL. - pluginSpec, err := workspace.NewPluginSpec(ctx, source, apitype.ResourcePlugin, nil, "", nil) + pluginSpec, err := workspace.NewPluginDescriptor(ctx, source, apitype.ResourcePlugin, nil, "", nil) var pluginErr workspace.PluginVersionNotFoundError if err != nil && !errors.As(err, &pluginErr) { // If we can't parse it as a plugin spec, assume it's a local path @@ -358,17 +356,20 @@ var _ Host = (*defaultHost)(nil) type analyzerPlugin struct { Plugin Analyzer - Info workspace.PluginInfo + Info PluginInfo + Name string } type languagePlugin struct { Plugin LanguageRuntime - Info workspace.PluginInfo + Info PluginInfo + Name string } type resourcePlugin struct { Plugin Provider - Info workspace.PluginInfo + Info PluginInfo + Name string } func (host *defaultHost) ServerAddr() string { @@ -436,7 +437,7 @@ func (host *defaultHost) Analyzer(name tokens.QName) (Analyzer, error) { } // Memoize the result. - host.analyzerPlugins[name] = &analyzerPlugin{Plugin: plug, Info: info} + host.analyzerPlugins[name] = &analyzerPlugin{Plugin: plug, Info: info, Name: string(name)} } return plug, err @@ -483,7 +484,7 @@ func (host *defaultHost) ListAnalyzers() []Analyzer { return analyzers } -func (host *defaultHost) Provider(descriptor workspace.PackageDescriptor) (Provider, error) { +func (host *defaultHost) Provider(descriptor workspace.PluginDescriptor) (Provider, error) { plugin, err := host.loadPlugin(host.loadRequests, func() (any, error) { pkg := descriptor.Name version := descriptor.Version @@ -503,7 +504,7 @@ func (host *defaultHost) Provider(descriptor workspace.PackageDescriptor) (Provi } plug, err := NewProvider( - host, host.ctx, descriptor.PluginDescriptor, + host, host.ctx, descriptor, host.runtimeOptions, host.disableProviderPreview, string(jsonConfig), host.projectName) if err == nil && plug != nil { info, infoerr := plug.GetPluginInfo(host.ctx.Request()) @@ -522,13 +523,13 @@ func (host *defaultHost) Provider(descriptor workspace.PackageDescriptor) (Provi diag.Message("", /*urn*/ "resource plugin %s is expected to have version >=%s, but has %s; "+ "the wrong version may be on your path, or this may be a bug in the plugin"), - info.Name, version.String(), v) + pkg, version.String(), v) } } // Record the result and add the plugin's info to our list of loaded plugins if it's the first copy of its // kind. - key := info.Name + key := pkg if info.Version != nil { key += info.Version.String() } @@ -536,7 +537,7 @@ func (host *defaultHost) Provider(descriptor workspace.PackageDescriptor) (Provi if !alreadyReported { host.reportedResourcePlugins[key] = struct{}{} } - host.resourcePlugins[plug] = &resourcePlugin{Plugin: plug, Info: info} + host.resourcePlugins[plug] = &resourcePlugin{Plugin: plug, Info: info, Name: pkg} } return plug, err @@ -546,7 +547,28 @@ func (host *defaultHost) Provider(descriptor workspace.PackageDescriptor) (Provi } provider := plugin.(Provider) - return provider, nil + return hostManagedProvider{provider, host}, nil +} + +// hostManagedProvider wraps a Provider such that it can be closed by the host that created it. +type hostManagedProvider struct { + Provider + + host *defaultHost +} + +// Overrides the wrapped provider's implementation of Provider.Close to ask the managing plugin host to close the +// provider. +func (pc hostManagedProvider) Close() error { + // NOTE: we're abusing loadPlugin in order to ensure proper synchronization. + _, err := pc.host.loadPlugin(pc.host.loadRequests, func() (any, error) { + if err := pc.Provider.Close(); err != nil { + return nil, err + } + delete(pc.host.resourcePlugins, pc.Provider) + return nil, nil + }) + return err } func (host *defaultHost) LanguageRuntime(runtime string, @@ -568,7 +590,7 @@ func (host *defaultHost) LanguageRuntime(runtime string, } // Memoize the result. - host.languagePlugins[runtime] = &languagePlugin{Plugin: plug, Info: info} + host.languagePlugins[runtime] = &languagePlugin{Plugin: plug, Info: info, Name: runtime} } return plug, err @@ -602,7 +624,7 @@ func (host *defaultHost) EnsurePlugins(plugins []workspace.PluginDescriptor, kin } case apitype.ResourcePlugin: if kinds&ResourcePlugins != 0 { - if _, err := host.Provider(workspace.PackageDescriptor{PluginDescriptor: plugin}); err != nil { + if _, err := host.Provider(plugin); err != nil { result = multierror.Append(result, fmt.Errorf("failed to load resource plugin %s: %w", plugin.Name, err)) } @@ -630,21 +652,21 @@ func (host *defaultHost) SignalCancellation() error { for _, plug := range host.resourcePlugins { if err := plug.Plugin.SignalCancellation(host.ctx.Request()); err != nil { result = multierror.Append(result, fmt.Errorf( - "Error signaling cancellation to resource provider '%s': %w", plug.Info.Name, err)) + "Error signaling cancellation to resource provider '%s': %w", plug.Name, err)) } } for _, plug := range host.analyzerPlugins { if err := plug.Plugin.Cancel(host.ctx.Request()); err != nil { result = multierror.Append(result, fmt.Errorf( - "Error signaling cancellation to analyzer '%s': %w", plug.Info.Name, err)) + "Error signaling cancellation to analyzer '%s': %w", plug.Name, err)) } } for _, plug := range host.languagePlugins { if err := plug.Plugin.Cancel(); err != nil { result = multierror.Append(result, fmt.Errorf( - "Error signaling cancellation to language runtime '%s': %w", plug.Info.Name, err)) + "Error signaling cancellation to language runtime '%s': %w", plug.Name, err)) } } return nil, result @@ -652,18 +674,6 @@ func (host *defaultHost) SignalCancellation() error { return err } -func (host *defaultHost) CloseProvider(provider Provider) error { - // NOTE: we're abusing loadPlugin in order to ensure proper synchronization. - _, err := host.loadPlugin(host.loadRequests, func() (any, error) { - if err := provider.Close(); err != nil { - return nil, err - } - delete(host.resourcePlugins, provider) - return nil, nil - }) - return err -} - func (host *defaultHost) Close() (err error) { host.closer.Do(func() { // Wait for all plugins to finish loading, we do this by taking a Write lock on the pluginLock. This @@ -675,17 +685,17 @@ func (host *defaultHost) Close() (err error) { // Close all plugins. for _, plug := range host.analyzerPlugins { if err := plug.Plugin.Close(); err != nil { - logging.V(5).Infof("Error closing '%s' analyzer plugin during shutdown; ignoring: %v", plug.Info.Name, err) + logging.V(5).Infof("Error closing '%s' analyzer plugin during shutdown; ignoring: %v", plug.Name, err) } } for _, plug := range host.resourcePlugins { if err := plug.Plugin.Close(); err != nil { - logging.V(5).Infof("Error closing '%s' resource plugin during shutdown; ignoring: %v", plug.Info.Name, err) + logging.V(5).Infof("Error closing '%s' resource plugin during shutdown; ignoring: %v", plug.Name, err) } } for _, plug := range host.languagePlugins { if err := plug.Plugin.Close(); err != nil { - logging.V(5).Infof("Error closing '%s' language plugin during shutdown; ignoring: %v", plug.Info.Name, err) + logging.V(5).Infof("Error closing '%s' language plugin during shutdown; ignoring: %v", plug.Name, err) } } diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/langruntime.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/langruntime.go index ea4dd5a89..956734280 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/langruntime.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/langruntime.go @@ -132,7 +132,7 @@ type LanguageRuntime interface { // return result.Bail immediately and not print any further messages to the user. Run(info RunInfo) (string, bool, error) // GetPluginInfo returns this plugin's information. - GetPluginInfo() (workspace.PluginInfo, error) + GetPluginInfo() (PluginInfo, error) // InstallDependencies will install dependencies for the project, e.g. by running `npm install` for nodejs projects. // It returns io.Readers for stdout and stderr as well as a channel that will be closed when the operation is diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/langruntime_plugin.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/langruntime_plugin.go index 2b1af5093..0c36d7500 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/langruntime_plugin.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/langruntime_plugin.go @@ -416,30 +416,23 @@ func (h *langhost) Run(info RunInfo) (string, bool, error) { } // GetPluginInfo returns this plugin's information. -func (h *langhost) GetPluginInfo() (workspace.PluginInfo, error) { +func (h *langhost) GetPluginInfo() (PluginInfo, error) { logging.V(7).Infof("langhost[%v].GetPluginInfo() executing", h.runtime) - plugInfo := workspace.PluginInfo{ - Name: h.runtime, - Kind: apitype.LanguagePlugin, - } - - if h.plug != nil { - plugInfo.Path = h.plug.Bin - } - resp, err := h.client.GetPluginInfo(h.ctx.Request(), &emptypb.Empty{}) if err != nil { rpcError := rpcerror.Convert(err) logging.V(7).Infof("langhost[%v].GetPluginInfo() failed: err=%v", h.runtime, rpcError) - return workspace.PluginInfo{}, rpcError + return PluginInfo{}, rpcError } vers := resp.Version + plugInfo := PluginInfo{} + if vers != "" { sv, err := semver.ParseTolerant(vers) if err != nil { - return workspace.PluginInfo{}, err + return PluginInfo{}, err } plugInfo.Version = &sv } diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/mock.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/mock.go index 09485aee8..a229b4cea 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/mock.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/mock.go @@ -31,8 +31,7 @@ type MockHost struct { AnalyzerF func(nm tokens.QName) (Analyzer, error) PolicyAnalyzerF func(name tokens.QName, path string, opts *PolicyAnalyzerOptions) (Analyzer, error) ListAnalyzersF func() []Analyzer - ProviderF func(descriptor workspace.PackageDescriptor) (Provider, error) - CloseProviderF func(provider Provider) error + ProviderF func(descriptor workspace.PluginDescriptor) (Provider, error) LanguageRuntimeF func(runtime string) (LanguageRuntime, error) EnsurePluginsF func(plugins []workspace.PluginDescriptor, kinds Flags) error ResolvePluginF func(spec workspace.PluginDescriptor) (*workspace.PluginInfo, error) @@ -85,20 +84,13 @@ func (m *MockHost) ListAnalyzers() []Analyzer { return nil } -func (m *MockHost) Provider(descriptor workspace.PackageDescriptor) (Provider, error) { +func (m *MockHost) Provider(descriptor workspace.PluginDescriptor) (Provider, error) { if m.ProviderF != nil { return m.ProviderF(descriptor) } return nil, errors.New("Provider not implemented") } -func (m *MockHost) CloseProvider(provider Provider) error { - if m.CloseProviderF != nil { - return m.CloseProviderF(provider) - } - return nil -} - func (m *MockHost) LanguageRuntime(runtime string) (LanguageRuntime, error) { if m.LanguageRuntimeF != nil { return m.LanguageRuntimeF(runtime) @@ -177,7 +169,7 @@ type MockProvider struct { ConstructF func(context.Context, ConstructRequest) (ConstructResponse, error) InvokeF func(context.Context, InvokeRequest) (InvokeResponse, error) CallF func(context.Context, CallRequest) (CallResponse, error) - GetPluginInfoF func(context.Context) (workspace.PluginInfo, error) + GetPluginInfoF func(context.Context) (PluginInfo, error) SignalCancellationF func(context.Context) error GetMappingF func(context.Context, GetMappingRequest) (GetMappingResponse, error) GetMappingsF func(context.Context, GetMappingsRequest) (GetMappingsResponse, error) @@ -306,11 +298,11 @@ func (m *MockProvider) Call(ctx context.Context, req CallRequest) (CallResponse, return CallResponse{}, errors.New("Call not implemented") } -func (m *MockProvider) GetPluginInfo(ctx context.Context) (workspace.PluginInfo, error) { +func (m *MockProvider) GetPluginInfo(ctx context.Context) (PluginInfo, error) { if m.GetPluginInfoF != nil { return m.GetPluginInfoF(ctx) } - return workspace.PluginInfo{}, errors.New("GetPluginInfo not implemented") + return PluginInfo{}, errors.New("GetPluginInfo not implemented") } func (m *MockProvider) SignalCancellation(ctx context.Context) error { diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/plugin.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/plugin.go index 754b7ca96..69a868abd 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/plugin.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/plugin.go @@ -1,4 +1,4 @@ -// Copyright 2016-2022, Pulumi Corporation. +// Copyright 2016-2026, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -32,6 +32,7 @@ import ( "syscall" "time" + "github.com/blang/semver" multierror "github.com/hashicorp/go-multierror" opentracing "github.com/opentracing/opentracing-go" "google.golang.org/grpc" @@ -47,6 +48,7 @@ import ( "github.com/pulumi/pulumi/sdk/v3/go/common/util/contract" "github.com/pulumi/pulumi/sdk/v3/go/common/util/logging" "github.com/pulumi/pulumi/sdk/v3/go/common/util/rpcutil/rpcerror" + "github.com/pulumi/pulumi/sdk/v3/go/common/version" "github.com/pulumi/pulumi/sdk/v3/go/common/workspace" ) @@ -458,6 +460,7 @@ func ExecPlugin(ctx *Context, bin, prefix string, kind apitype.PluginKind, } var runtimeInfo workspace.ProjectRuntimeInfo + var pulumiVersionRange string switch kind { //nolint:exhaustive // golangci-lint v2 upgrade case apitype.ResourcePlugin, apitype.ConverterPlugin: proj, err := workspace.LoadPluginProject(filepath.Join(pluginDir, "PulumiPlugin.yaml")) @@ -465,16 +468,22 @@ func ExecPlugin(ctx *Context, bin, prefix string, kind apitype.PluginKind, return nil, fmt.Errorf("loading PulumiPlugin.yaml: %w", err) } runtimeInfo = proj.Runtime + pulumiVersionRange = proj.PulumiVersionRange case apitype.AnalyzerPlugin: proj, err := workspace.LoadPluginProject(filepath.Join(pluginDir, "PulumiPolicy.yaml")) if err != nil { return nil, fmt.Errorf("loading PulumiPolicy.yaml: %w", err) } runtimeInfo = proj.Runtime + pulumiVersionRange = proj.PulumiVersionRange default: return nil, errors.New("language plugins must be executable binaries") } + if err := validatePulumiVersionRange(pulumiVersionRange, version.Version, pluginDir); err != nil { + return nil, err + } + logging.V(9).Infof("Launching plugin '%v' from '%v' via runtime '%s'", prefix, pluginDir, runtimeInfo.Name()) // ProgramInfo needs pluginDir to be an absolute path @@ -618,6 +627,33 @@ func ExecPlugin(ctx *Context, bin, prefix string, kind apitype.PluginKind, }, nil } +// validatePulumiVersionRange validates that the CLI version satisfies the passed version range. The supported syntax +// for ranges is that of https://pkg.go.dev/github.com/blang/semver#ParseRange. For example ">=3.0.0", or "!3.1.2". +// Ranges can be AND-ed together by concatenating with spaces ">=3.5.0 !3.7.7", meaning greater-or-equal to 3.5.0 and +// not exactly 3.7.7. Ranges can be OR-ed with the `||` operator: "<3.4.0 || >3.8.0", meaning less-than 3.4.0 or +// greater-than 3.8.0. +func validatePulumiVersionRange(pulumiVersionRange, cliVersion, provider string) error { + // The cliVersion is the build version and will usually be set when running the Pulumi CLI, however it may be empty + // when running non-integration tests. + if pulumiVersionRange != "" && cliVersion != "" { + rg, err := semver.ParseRange(pulumiVersionRange) + if err != nil { + return fmt.Errorf("parsing CLI version range %q: %w", pulumiVersionRange, err) + } + cliVersion, err := semver.ParseTolerant(cliVersion) + if err != nil { + return fmt.Errorf("parsing CLI version %q: %w", version.Version, err) + } + if !rg(cliVersion) { + return fmt.Errorf( + "Pulumi CLI version %s does not satisfy the version range %q requested by the provider %s.", + cliVersion, pulumiVersionRange, provider, + ) + } + } + return nil +} + type pluginArgumentOptions struct { pluginArgs []string tracingEndpoint string diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/plugin_info.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/plugin_info.go new file mode 100644 index 000000000..598cd24c5 --- /dev/null +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/plugin_info.go @@ -0,0 +1,25 @@ +// Copyright 2025, Pulumi Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugin + +import ( + "github.com/blang/semver" +) + +// PluginInfo is meta-information about a plugin that is used by the system. +type PluginInfo struct { + // The semver for this plugin. + Version *semver.Version +} diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider.go index 5cdefa75f..fac273d1f 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider.go @@ -1,4 +1,4 @@ -// Copyright 2016-2025, Pulumi Corporation. +// Copyright 2016-2026, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ import ( "github.com/pulumi/pulumi/sdk/v3/go/common/resource/config" "github.com/pulumi/pulumi/sdk/v3/go/common/tokens" "github.com/pulumi/pulumi/sdk/v3/go/common/util/contract" - "github.com/pulumi/pulumi/sdk/v3/go/common/workspace" ) type GetSchemaRequest struct { @@ -85,6 +84,14 @@ type ProviderHandshakeResponse struct { // True if the provider accepts and respects autonaming configuration that the engine provides on behalf of the // user. SupportsAutonamingConfiguration bool + + // The CLI version range required for this provider to work correctly. Empty if the provider does not have a version + // requirement. + // The supported syntax for ranges is that of https://pkg.go.dev/github.com/blang/semver#ParseRange. For example + // ">=3.0.0", or "!3.1.2". Ranges can be AND-ed together by concatenating with spaces ">=3.5.0 !3.7.7", meaning + // greater-or-equal to 3.5.0 and not exactly 3.7.7. Ranges can be OR-ed with the `||` operator: "<3.4.0 || >3.8.0", + // meaning less-than 3.4.0 or greater-than 3.8.0. + PulumiVersionRange string } // ParameterizeParameters can either be of concrete type ParameterizeArgs or ParameterizeValue, for when parameterizing @@ -457,7 +464,7 @@ type Provider interface { Call(context.Context, CallRequest) (CallResponse, error) // GetPluginInfo returns this plugin's information. - GetPluginInfo(context.Context) (workspace.PluginInfo, error) + GetPluginInfo(context.Context) (PluginInfo, error) // SignalCancellation asks all resource providers to gracefully shut down and abort any ongoing // operations. Operation aborted in this way will return an error (e.g., `Update` and `Create` diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_plugin.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_plugin.go index d6aba72a0..426683e99 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_plugin.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_plugin.go @@ -1,4 +1,4 @@ -// Copyright 2016-2025, Pulumi Corporation. +// Copyright 2016-2026, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -48,6 +48,7 @@ import ( "github.com/pulumi/pulumi/sdk/v3/go/common/util/logging" "github.com/pulumi/pulumi/sdk/v3/go/common/util/rpcutil" "github.com/pulumi/pulumi/sdk/v3/go/common/util/rpcutil/rpcerror" + "github.com/pulumi/pulumi/sdk/v3/go/common/version" "github.com/pulumi/pulumi/sdk/v3/go/common/workspace" pulumirpc "github.com/pulumi/pulumi/sdk/v3/proto/go" ) @@ -289,6 +290,11 @@ func NewProvider(host Host, ctx *Context, spec workspace.PluginDescriptor, } if handshakeRes != nil { + if err := validatePulumiVersionRange(handshakeRes.PulumiVersionRange, version.Version, string(pkg)); err != nil { + contract.IgnoreClose(p) + return nil, err + } + p.protocol = &pluginProtocol{ acceptSecrets: handshakeRes.AcceptSecrets, acceptResources: handshakeRes.AcceptResources, @@ -342,6 +348,7 @@ func handshake( AcceptResources: res.GetAcceptResources(), AcceptOutputs: res.GetAcceptOutputs(), SupportsAutonamingConfiguration: res.GetSupportsAutonamingConfiguration(), + PulumiVersionRange: res.GetPulumiVersionRange(), }, nil } @@ -370,7 +377,7 @@ func providerPluginDialOptions(ctx *Context, pkg tokens.Package, path string) [] } // NewProviderFromPath creates a new provider by loading the plugin binary located at `path`. -func NewProviderFromPath(host Host, ctx *Context, path string) (Provider, error) { +func NewProviderFromPath(host Host, ctx *Context, pkg tokens.Package, path string) (Provider, error) { env := os.Environ() handshake := func( @@ -406,9 +413,15 @@ func NewProviderFromPath(host Host, ctx *Context, path string) (Provider, error) clientRaw: pulumirpc.NewResourceProviderClient(plug.Conn), legacyPreview: legacyPreview, configSource: &promise.CompletionSource[pluginConfig]{}, + pkg: pkg, } if handshakeRes != nil { + if err := validatePulumiVersionRange(handshakeRes.PulumiVersionRange, version.Version, string(pkg)); err != nil { + contract.IgnoreClose(p) + return nil, err + } + p.protocol = &pluginProtocol{ acceptSecrets: handshakeRes.AcceptSecrets, acceptResources: handshakeRes.AcceptResources, @@ -511,6 +524,7 @@ func (p *provider) Handshake(ctx context.Context, req ProviderHandshakeRequest) AcceptResources: res.GetAcceptResources(), AcceptOutputs: res.GetAcceptOutputs(), SupportsAutonamingConfiguration: res.GetSupportsAutonamingConfiguration(), + PulumiVersionRange: res.GetPulumiVersionRange(), }, nil } @@ -2140,7 +2154,7 @@ func (p *provider) Call(_ context.Context, req CallRequest) (CallResponse, error } // GetPluginInfo returns this plugin's information. -func (p *provider) GetPluginInfo(ctx context.Context) (workspace.PluginInfo, error) { +func (p *provider) GetPluginInfo(ctx context.Context) (PluginInfo, error) { label := p.label() + ".GetPluginInfo()" logging.V(7).Infof("%s executing", label) @@ -2154,28 +2168,20 @@ func (p *provider) GetPluginInfo(ctx context.Context) (workspace.PluginInfo, err if err != nil { rpcError := rpcerror.Convert(err) logging.V(7).Infof("%s failed: err=%v", label, rpcError.Message()) - return workspace.PluginInfo{}, rpcError + return PluginInfo{}, rpcError } if v := resp.Version; v != "" { sv, err := semver.ParseTolerant(v) if err != nil { - return workspace.PluginInfo{}, err + return PluginInfo{}, err } version = &sv } } - path := "" - if p.plug != nil { - path = p.plug.Bin - } - logging.V(7).Infof("%s success (#version=%v) success", label, version) - return workspace.PluginInfo{ - Name: string(p.pkg), - Path: path, - Kind: apitype.ResourcePlugin, + return PluginInfo{ Version: version, }, nil } diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_server.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_server.go index 775d6f96e..5b7cdcc7d 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_server.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_server.go @@ -1,4 +1,4 @@ -// Copyright 2016-2025, Pulumi Corporation. +// Copyright 2016-2026, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -160,6 +160,7 @@ func (p *providerServer) Handshake( // For features we don't shim, we just pass through the response from the provider as expected. SupportsAutonamingConfiguration: res.SupportsAutonamingConfiguration, + PulumiVersionRange: &res.PulumiVersionRange, }, nil } diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_unimplemented.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_unimplemented.go index 433f2a016..671ec5a81 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_unimplemented.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin/provider_unimplemented.go @@ -18,7 +18,6 @@ import ( "context" "github.com/pulumi/pulumi/sdk/v3/go/common/tokens" - "github.com/pulumi/pulumi/sdk/v3/go/common/workspace" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -110,8 +109,8 @@ func (p *UnimplementedProvider) Call(context.Context, CallRequest) (CallResponse return CallResponse{}, status.Error(codes.Unimplemented, "Call is not yet implemented") } -func (p *UnimplementedProvider) GetPluginInfo(context.Context) (workspace.PluginInfo, error) { - return workspace.PluginInfo{}, status.Error(codes.Unimplemented, "GetPluginInfo is not yet implemented") +func (p *UnimplementedProvider) GetPluginInfo(context.Context) (PluginInfo, error) { + return PluginInfo{}, status.Error(codes.Unimplemented, "GetPluginInfo is not yet implemented") } func (p *UnimplementedProvider) GetMapping(context.Context, GetMappingRequest) (GetMappingResponse, error) { diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/plugins.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/plugins.go index 4cd96e7a8..7d4fb8a65 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/plugins.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/plugins.go @@ -63,6 +63,8 @@ const ( var enableLegacyPluginBehavior = os.Getenv("PULUMI_ENABLE_LEGACY_PLUGIN_SEARCH") != "" +var ErrGetLatestVersionNotSupported = errors.New("GetLatestVersion is not supported for plugins from http sources") + // pluginDownloadURLOverrides is a variable instead of a constant so it can be set using the `-X` `ldflag` at build // time, if necessary. When non-empty, it's parsed into `pluginDownloadURLOverridesParsed` in `init()`. The expected // format is `regexp=URL`, and multiple pairs can be specified separated by commas, e.g. `regexp1=URL1,regexp2=URL2`. @@ -239,6 +241,10 @@ func (source *getPulumiSource) Download( return getHTTPResponse(req) } +func (source *getPulumiSource) url() string { + return "https://get.pulumi.com/releases/plugins" +} + // gitlabSource can download a plugin from gitlab releases. type gitlabSource struct { host string @@ -694,7 +700,7 @@ func (source *httpSource) GetLatestVersion( ctx context.Context, getHTTPResponse func(*http.Request) (io.ReadCloser, int64, error), ) (*semver.Version, error) { - return nil, errors.New("GetLatestVersion is not supported for plugins from http sources") + return nil, ErrGetLatestVersionNotSupported } func interpolateURL(serverURL string, name string, version semver.Version, os, arch string) string { @@ -785,6 +791,19 @@ func (source *fallbackSource) Download( // Fallback to get.pulumi.com pulumi := newGetPulumiSource(source.name, source.kind) + // Check if there's a URL override for the get.pulumi.com URL. + // Note: This check is necessary because GetSource() checks overrides against fallbackSource.URL() + // which returns the GitHub URL, not the get.pulumi.com URL. When we actually fall back to + // get.pulumi.com here, we need to check if there's an override for that specific URL. + if overrideURL, ok := pluginDownloadURLOverridesParsed.get(pulumi.url()); ok { + logging.V(1).Infof("Applying URL override for %s: %s -> %s", source.name, pulumi.url(), overrideURL) + overrideSource, err := newPluginSource(source.name, source.kind, overrideURL) + if err != nil { + return nil, 0, fmt.Errorf("unable to construct override for %q: %w", source.name, err) + } + return overrideSource.Download(ctx, version, opSy, arch, getHTTPResponse) + } + return pulumi.Download(ctx, version, opSy, arch, getHTTPResponse) } @@ -891,7 +910,7 @@ type ProjectPlugin struct { // Spec Return a PluginSpec object for this project plugin. func (pp ProjectPlugin) Spec(ctx context.Context) (PluginDescriptor, error) { - return NewPluginSpec(ctx, pp.Name, pp.Kind, pp.Version, "", nil) + return NewPluginDescriptor(ctx, pp.Name, pp.Kind, pp.Version, "", nil) } // LinkablePackageDescriptor contains the information necessary to link an SDK for a package specified by a @@ -914,6 +933,17 @@ type PackageDescriptor struct { Parameterization *Parameterization } +// A resolved plugin with parameterization arguments. +// +// This is different then a [PackageDescriptor], which holds a parameterization value. +type UnresolvedPackageDescriptor struct { + // The fully resolved plugin descriptor. + PluginDescriptor + + // The parameterization args to be applied against the plugin descriptor. + ParameterizationArgs []string +} + func NewPackageDescriptor(spec PluginDescriptor, parameterization *Parameterization) PackageDescriptor { return PackageDescriptor{ PluginDescriptor: spec, @@ -1028,6 +1058,12 @@ var gitCommitHashRegex = sync.OnceValue(func() *regexp.Regexp { return regexp.MustCompile(`^[0-9a-fA-F]{4,64}$`) }) +// NewPluginDescriptor creates a new [PluginDescriptor] from a source string. +// +// If you are using this to resolve a "package", consider using +// [packageresolution.Resolve] instead. +// +// Deprecated: NewPluginSpec has been renamed to [NewPluginDescriptor]. func NewPluginSpec( ctx context.Context, source string, @@ -1035,6 +1071,21 @@ func NewPluginSpec( version *semver.Version, pluginDownloadURL string, checksums map[string][]byte, +) (PluginDescriptor, error) { + return NewPluginDescriptor(ctx, source, kind, version, pluginDownloadURL, checksums) +} + +// NewPluginDescriptor creates a new [PluginDescriptor] from a source string. +// +// If you are using this to resolve a "package", consider using +// [packageresolution.Resolve] instead. +func NewPluginDescriptor( + ctx context.Context, + source string, + kind apitype.PluginKind, + version *semver.Version, + pluginDownloadURL string, + checksums map[string][]byte, ) (PluginDescriptor, error) { spec, inference, err := parsePluginSpec(ctx, source, kind) if err != nil { @@ -1777,17 +1828,18 @@ func HasPlugin(spec PluginDescriptor) bool { return false } -// HasPluginGTE returns true if the given plugin exists at the given version number or greater. -func HasPluginGTE(spec PluginDescriptor) (bool, error) { +// HasPluginGTE returns the version selected if the given plugin exists at the given +// version number or greater. +func HasPluginGTE(spec PluginDescriptor) (bool, *semver.Version, error) { // If an exact match, return true right away. if HasPlugin(spec) { - return true, nil + return true, spec.Version, nil } // Otherwise, load up the list of plugins and find one with the same name/type and >= version. plugs, err := GetPlugins() if err != nil { - return false, err + return false, nil, err } // If we're not doing the legacy plugin behavior and we've been asked for a specific version, do the same plugin @@ -1799,7 +1851,10 @@ func HasPluginGTE(spec PluginDescriptor) (bool, error) { } else { match = LegacySelectCompatiblePlugin(plugs, spec) } - return match != nil, nil + if match != nil { + return true, match.Version, nil + } + return false, nil, nil } // GetPolicyDir returns the directory in which an organization's Policy Packs on the current machine are managed. diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/project.go b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/project.go index 52b85bd14..e56a3f619 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/project.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/project.go @@ -1,4 +1,4 @@ -// Copyright 2016-2022, Pulumi Corporation. +// Copyright 2016-2026, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -115,6 +115,7 @@ type PackageSpec struct { // - A simple name, like "pkg" // - A registry double or triple: "org/pkg", "source/org/pkg" // - A git URL, "git://github.com/pulumi/pulumi-example/path" + // - An un-prefixed URL, like github.com/pulumi/pulumi-example/path // - A local path, like /usr/bin/pkg Source string // The version of the provider, may be Semver 2.0 or a git hash. @@ -135,7 +136,7 @@ type PackageSpec struct { type packageSpecMarshalled struct { Source string `json:"source" yaml:"source"` - Version string `json:"version" yaml:"version"` + Version string `json:"version,omitzero" yaml:"version,omitempty"` Parameters []string `json:"parameters,omitzero" yaml:"parameters,omitempty"` Checksums map[string][]byte `json:"checksums,omitzero" yaml:"checksums,omitempty"` PluginDownloadURL string `json:"pluginDownloadURL,omitzero" yaml:"pluginDownloadURL,omitempty"` @@ -900,6 +901,12 @@ type PluginProject struct { Runtime ProjectRuntimeInfo `json:"runtime" yaml:"runtime"` // Packages is a map of package dependencies that can be either strings or PackageSpecs Packages map[string]PackageSpec `json:"packages,omitempty" yaml:"packages,omitempty"` + // The CLI version range required for this provider to work correctly. If no version range is specified, the + // provider will be considered compatible with any CLI version. The supported syntax for ranges is that of + // https://pkg.go.dev/github.com/blang/semver#ParseRange. For example ">=3.0.0", or "!3.1.2". Ranges can be AND-ed + // together by concatenating with spaces ">=3.5.0 !3.7.7", meaning greater-or-equal to 3.5.0 and not exactly 3.7.7. + // Ranges can be OR-ed with the `||` operator: "<3.4.0 || >3.8.0", meaning less-than 3.4.0 or greater-than 3.8.0. + PulumiVersionRange string `json:"pulumiVersionRange" yaml:"pulumiVersionRange"` } var _ BaseProject = (*PluginProject)(nil) diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/project.json b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/project.json index ba727d5f0..2c338dc23 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/project.json +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/go/common/workspace/project.json @@ -289,6 +289,17 @@ "type": "string" }, "description":"Additional parameters for parameterized providers" + }, + "pluginDownloadURL":{ + "type": "string", + "description":"The server from which to download the provider plugin from" + }, + "checksums":{ + "type": "object", + "description":"The checksums of the downloaded plugin, by os-arch", + "additionalProperties": { + "type": "string" + } } } }, diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/proto/go/provider.pb.go b/vendor/github.com/pulumi/pulumi/sdk/v3/proto/go/provider.pb.go index 2b4d611ba..4f202bc26 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/proto/go/provider.pb.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/proto/go/provider.pb.go @@ -1,4 +1,4 @@ -// Copyright 2016-2025, Pulumi Corporation. +// Copyright 2016-2026, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -334,8 +334,15 @@ type ProviderHandshakeResponse struct { // True if the provider accepts and respects autonaming configuration that the engine provides on behalf of the // user. *Must* match the value returned in response to [](pulumirpc.ResourceProvider.Configure). SupportsAutonamingConfiguration bool `protobuf:"varint,4,opt,name=supports_autonaming_configuration,json=supportsAutonamingConfiguration,proto3" json:"supports_autonaming_configuration,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // The CLI version range required for this provider to work correctly. If no version range is specified, the + // provider will be considered compatible with any CLI version. + // The supported syntax for ranges is that of https://pkg.go.dev/github.com/blang/semver#ParseRange. For example + // ">=3.0.0", or "!3.1.2". Ranges can be AND-ed together by concatenating with spaces ">=3.5.0 !3.7.7", meaning + // greater-or-equal to 3.5.0 and not exactly 3.7.7. Ranges can be OR-ed with the `||` operator: "<3.4.0 || >3.8.0", + // meaning less-than 3.4.0 or greater-than 3.8.0. + PulumiVersionRange *string `protobuf:"bytes,5,opt,name=pulumi_version_range,json=pulumiVersionRange,proto3,oneof" json:"pulumi_version_range,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ProviderHandshakeResponse) Reset() { @@ -396,6 +403,13 @@ func (x *ProviderHandshakeResponse) GetSupportsAutonamingConfiguration() bool { return false } +func (x *ProviderHandshakeResponse) GetPulumiVersionRange() string { + if x != nil && x.PulumiVersionRange != nil { + return *x.PulumiVersionRange + } + return "" +} + // `ParameterizeRequest` is the type of requests sent as part of a [](pulumirpc.ResourceProvider.Parameterize) call. A // `ParameterizeRequest` may contain either: // @@ -3895,12 +3909,14 @@ const file_pulumi_provider_proto_rawDesc = "" + "\x1esupports_refresh_before_update\x18\x06 \x01(\bR\x1bsupportsRefreshBeforeUpdate\x12.\n" + "\x13invoke_with_preview\x18\a \x01(\bR\x11invokeWithPreviewB\x11\n" + "\x0f_root_directoryB\x14\n" + - "\x12_program_directory\"\xe0\x01\n" + + "\x12_program_directory\"\xb0\x02\n" + "\x19ProviderHandshakeResponse\x12%\n" + "\x0eaccept_secrets\x18\x01 \x01(\bR\racceptSecrets\x12)\n" + "\x10accept_resources\x18\x02 \x01(\bR\x0facceptResources\x12%\n" + "\x0eaccept_outputs\x18\x03 \x01(\bR\racceptOutputs\x12J\n" + - "!supports_autonaming_configuration\x18\x04 \x01(\bR\x1fsupportsAutonamingConfiguration\"\xad\x02\n" + + "!supports_autonaming_configuration\x18\x04 \x01(\bR\x1fsupportsAutonamingConfiguration\x125\n" + + "\x14pulumi_version_range\x18\x05 \x01(\tH\x00R\x12pulumiVersionRange\x88\x01\x01B\x17\n" + + "\x15_pulumi_version_range\"\xad\x02\n" + "\x13ParameterizeRequest\x12C\n" + "\x04args\x18\x01 \x01(\v2-.pulumirpc.ParameterizeRequest.ParametersArgsH\x00R\x04args\x12F\n" + "\x05value\x18\x02 \x01(\v2..pulumirpc.ParameterizeRequest.ParametersValueH\x00R\x05value\x1a$\n" + @@ -4432,6 +4448,7 @@ func file_pulumi_provider_proto_init() { } file_pulumi_plugin_proto_init() file_pulumi_provider_proto_msgTypes[0].OneofWrappers = []any{} + file_pulumi_provider_proto_msgTypes[1].OneofWrappers = []any{} file_pulumi_provider_proto_msgTypes[2].OneofWrappers = []any{ (*ParameterizeRequest_Args)(nil), (*ParameterizeRequest_Value)(nil), diff --git a/vendor/github.com/pulumi/pulumi/sdk/v3/proto/go/provider_grpc.pb.go b/vendor/github.com/pulumi/pulumi/sdk/v3/proto/go/provider_grpc.pb.go index 0b704ef3a..7428b9cc8 100644 --- a/vendor/github.com/pulumi/pulumi/sdk/v3/proto/go/provider_grpc.pb.go +++ b/vendor/github.com/pulumi/pulumi/sdk/v3/proto/go/provider_grpc.pb.go @@ -1,4 +1,4 @@ -// Copyright 2016-2025, Pulumi Corporation. +// Copyright 2016-2026, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.go b/vendor/golang.org/x/sys/cpu/cpu_x86.go index 1e642f330..f5723d4f7 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_x86.go +++ b/vendor/golang.org/x/sys/cpu/cpu_x86.go @@ -64,6 +64,80 @@ func initOptions() { func archInit() { + // From internal/cpu + const ( + // eax bits + cpuid_AVXVNNI = 1 << 4 + + // ecx bits + cpuid_SSE3 = 1 << 0 + cpuid_PCLMULQDQ = 1 << 1 + cpuid_AVX512VBMI = 1 << 1 + cpuid_AVX512VBMI2 = 1 << 6 + cpuid_SSSE3 = 1 << 9 + cpuid_AVX512GFNI = 1 << 8 + cpuid_AVX512VAES = 1 << 9 + cpuid_AVX512VNNI = 1 << 11 + cpuid_AVX512BITALG = 1 << 12 + cpuid_FMA = 1 << 12 + cpuid_AVX512VPOPCNTDQ = 1 << 14 + cpuid_SSE41 = 1 << 19 + cpuid_SSE42 = 1 << 20 + cpuid_POPCNT = 1 << 23 + cpuid_AES = 1 << 25 + cpuid_OSXSAVE = 1 << 27 + cpuid_AVX = 1 << 28 + + // "Extended Feature Flag" bits returned in EBX for CPUID EAX=0x7 ECX=0x0 + cpuid_BMI1 = 1 << 3 + cpuid_AVX2 = 1 << 5 + cpuid_BMI2 = 1 << 8 + cpuid_ERMS = 1 << 9 + cpuid_AVX512F = 1 << 16 + cpuid_AVX512DQ = 1 << 17 + cpuid_ADX = 1 << 19 + cpuid_AVX512CD = 1 << 28 + cpuid_SHA = 1 << 29 + cpuid_AVX512BW = 1 << 30 + cpuid_AVX512VL = 1 << 31 + + // "Extended Feature Flag" bits returned in ECX for CPUID EAX=0x7 ECX=0x0 + cpuid_AVX512_VBMI = 1 << 1 + cpuid_AVX512_VBMI2 = 1 << 6 + cpuid_GFNI = 1 << 8 + cpuid_AVX512VPCLMULQDQ = 1 << 10 + cpuid_AVX512_BITALG = 1 << 12 + + // edx bits + cpuid_FSRM = 1 << 4 + // edx bits for CPUID 0x80000001 + cpuid_RDTSCP = 1 << 27 + ) + // Additional constants not in internal/cpu + const ( + // eax=1: edx + cpuid_SSE2 = 1 << 26 + // eax=1: ecx + cpuid_CX16 = 1 << 13 + cpuid_RDRAND = 1 << 30 + // eax=7,ecx=0: ebx + cpuid_RDSEED = 1 << 18 + cpuid_AVX512IFMA = 1 << 21 + cpuid_AVX512PF = 1 << 26 + cpuid_AVX512ER = 1 << 27 + // eax=7,ecx=0: edx + cpuid_AVX5124VNNIW = 1 << 2 + cpuid_AVX5124FMAPS = 1 << 3 + cpuid_AMXBF16 = 1 << 22 + cpuid_AMXTile = 1 << 24 + cpuid_AMXInt8 = 1 << 25 + // eax=7,ecx=1: eax + cpuid_AVX512BF16 = 1 << 5 + cpuid_AVXIFMA = 1 << 23 + // eax=7,ecx=1: edx + cpuid_AVXVNNIInt8 = 1 << 4 + ) + Initialized = true maxID, _, _, _ := cpuid(0, 0) @@ -73,90 +147,90 @@ func archInit() { } _, _, ecx1, edx1 := cpuid(1, 0) - X86.HasSSE2 = isSet(26, edx1) - - X86.HasSSE3 = isSet(0, ecx1) - X86.HasPCLMULQDQ = isSet(1, ecx1) - X86.HasSSSE3 = isSet(9, ecx1) - X86.HasFMA = isSet(12, ecx1) - X86.HasCX16 = isSet(13, ecx1) - X86.HasSSE41 = isSet(19, ecx1) - X86.HasSSE42 = isSet(20, ecx1) - X86.HasPOPCNT = isSet(23, ecx1) - X86.HasAES = isSet(25, ecx1) - X86.HasOSXSAVE = isSet(27, ecx1) - X86.HasRDRAND = isSet(30, ecx1) + X86.HasSSE2 = isSet(edx1, cpuid_SSE2) + + X86.HasSSE3 = isSet(ecx1, cpuid_SSE3) + X86.HasPCLMULQDQ = isSet(ecx1, cpuid_PCLMULQDQ) + X86.HasSSSE3 = isSet(ecx1, cpuid_SSSE3) + X86.HasFMA = isSet(ecx1, cpuid_FMA) + X86.HasCX16 = isSet(ecx1, cpuid_CX16) + X86.HasSSE41 = isSet(ecx1, cpuid_SSE41) + X86.HasSSE42 = isSet(ecx1, cpuid_SSE42) + X86.HasPOPCNT = isSet(ecx1, cpuid_POPCNT) + X86.HasAES = isSet(ecx1, cpuid_AES) + X86.HasOSXSAVE = isSet(ecx1, cpuid_OSXSAVE) + X86.HasRDRAND = isSet(ecx1, cpuid_RDRAND) var osSupportsAVX, osSupportsAVX512 bool // For XGETBV, OSXSAVE bit is required and sufficient. if X86.HasOSXSAVE { eax, _ := xgetbv() // Check if XMM and YMM registers have OS support. - osSupportsAVX = isSet(1, eax) && isSet(2, eax) + osSupportsAVX = isSet(eax, 1<<1) && isSet(eax, 1<<2) if runtime.GOOS == "darwin" { // Darwin requires special AVX512 checks, see cpu_darwin_x86.go osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512() } else { // Check if OPMASK and ZMM registers have OS support. - osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax) + osSupportsAVX512 = osSupportsAVX && isSet(eax, 1<<5) && isSet(eax, 1<<6) && isSet(eax, 1<<7) } } - X86.HasAVX = isSet(28, ecx1) && osSupportsAVX + X86.HasAVX = isSet(ecx1, cpuid_AVX) && osSupportsAVX if maxID < 7 { return } eax7, ebx7, ecx7, edx7 := cpuid(7, 0) - X86.HasBMI1 = isSet(3, ebx7) - X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX - X86.HasBMI2 = isSet(8, ebx7) - X86.HasERMS = isSet(9, ebx7) - X86.HasRDSEED = isSet(18, ebx7) - X86.HasADX = isSet(19, ebx7) - - X86.HasAVX512 = isSet(16, ebx7) && osSupportsAVX512 // Because avx-512 foundation is the core required extension + X86.HasBMI1 = isSet(ebx7, cpuid_BMI1) + X86.HasAVX2 = isSet(ebx7, cpuid_AVX2) && osSupportsAVX + X86.HasBMI2 = isSet(ebx7, cpuid_BMI2) + X86.HasERMS = isSet(ebx7, cpuid_ERMS) + X86.HasRDSEED = isSet(ebx7, cpuid_RDSEED) + X86.HasADX = isSet(ebx7, cpuid_ADX) + + X86.HasAVX512 = isSet(ebx7, cpuid_AVX512F) && osSupportsAVX512 // Because avx-512 foundation is the core required extension if X86.HasAVX512 { X86.HasAVX512F = true - X86.HasAVX512CD = isSet(28, ebx7) - X86.HasAVX512ER = isSet(27, ebx7) - X86.HasAVX512PF = isSet(26, ebx7) - X86.HasAVX512VL = isSet(31, ebx7) - X86.HasAVX512BW = isSet(30, ebx7) - X86.HasAVX512DQ = isSet(17, ebx7) - X86.HasAVX512IFMA = isSet(21, ebx7) - X86.HasAVX512VBMI = isSet(1, ecx7) - X86.HasAVX5124VNNIW = isSet(2, edx7) - X86.HasAVX5124FMAPS = isSet(3, edx7) - X86.HasAVX512VPOPCNTDQ = isSet(14, ecx7) - X86.HasAVX512VPCLMULQDQ = isSet(10, ecx7) - X86.HasAVX512VNNI = isSet(11, ecx7) - X86.HasAVX512GFNI = isSet(8, ecx7) - X86.HasAVX512VAES = isSet(9, ecx7) - X86.HasAVX512VBMI2 = isSet(6, ecx7) - X86.HasAVX512BITALG = isSet(12, ecx7) + X86.HasAVX512CD = isSet(ebx7, cpuid_AVX512CD) + X86.HasAVX512ER = isSet(ebx7, cpuid_AVX512ER) + X86.HasAVX512PF = isSet(ebx7, cpuid_AVX512PF) + X86.HasAVX512VL = isSet(ebx7, cpuid_AVX512VL) + X86.HasAVX512BW = isSet(ebx7, cpuid_AVX512BW) + X86.HasAVX512DQ = isSet(ebx7, cpuid_AVX512DQ) + X86.HasAVX512IFMA = isSet(ebx7, cpuid_AVX512IFMA) + X86.HasAVX512VBMI = isSet(ecx7, cpuid_AVX512_VBMI) + X86.HasAVX5124VNNIW = isSet(edx7, cpuid_AVX5124VNNIW) + X86.HasAVX5124FMAPS = isSet(edx7, cpuid_AVX5124FMAPS) + X86.HasAVX512VPOPCNTDQ = isSet(ecx7, cpuid_AVX512VPOPCNTDQ) + X86.HasAVX512VPCLMULQDQ = isSet(ecx7, cpuid_AVX512VPCLMULQDQ) + X86.HasAVX512VNNI = isSet(ecx7, cpuid_AVX512VNNI) + X86.HasAVX512GFNI = isSet(ecx7, cpuid_AVX512GFNI) + X86.HasAVX512VAES = isSet(ecx7, cpuid_AVX512VAES) + X86.HasAVX512VBMI2 = isSet(ecx7, cpuid_AVX512VBMI2) + X86.HasAVX512BITALG = isSet(ecx7, cpuid_AVX512BITALG) } - X86.HasAMXTile = isSet(24, edx7) - X86.HasAMXInt8 = isSet(25, edx7) - X86.HasAMXBF16 = isSet(22, edx7) + X86.HasAMXTile = isSet(edx7, cpuid_AMXTile) + X86.HasAMXInt8 = isSet(edx7, cpuid_AMXInt8) + X86.HasAMXBF16 = isSet(edx7, cpuid_AMXBF16) // These features depend on the second level of extended features. if eax7 >= 1 { eax71, _, _, edx71 := cpuid(7, 1) if X86.HasAVX512 { - X86.HasAVX512BF16 = isSet(5, eax71) + X86.HasAVX512BF16 = isSet(eax71, cpuid_AVX512BF16) } if X86.HasAVX { - X86.HasAVXIFMA = isSet(23, eax71) - X86.HasAVXVNNI = isSet(4, eax71) - X86.HasAVXVNNIInt8 = isSet(4, edx71) + X86.HasAVXIFMA = isSet(eax71, cpuid_AVXIFMA) + X86.HasAVXVNNI = isSet(eax71, cpuid_AVXVNNI) + X86.HasAVXVNNIInt8 = isSet(edx71, cpuid_AVXVNNIInt8) } } } -func isSet(bitpos uint, value uint32) bool { - return value&(1<